linux/drivers/staging/comedi/drivers/dt9812.c
<<
>>
Prefs
   1/*
   2 * comedi/drivers/dt9812.c
   3 *   COMEDI driver for DataTranslation DT9812 USB module
   4 *
   5 * Copyright (C) 2005 Anders Blomdell <anders.blomdell@control.lth.se>
   6 *
   7 * COMEDI - Linux Control and Measurement Device Interface
   8 *
   9 * This program is free software; you can redistribute it and/or modify
  10 * it under the terms of the GNU General Public License as published by
  11 * the Free Software Foundation; either version 2 of the License, or
  12 * (at your option) any later version.
  13
  14 *  This program is distributed in the hope that it will be useful,
  15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
  16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  17 * GNU General Public License for more details.
  18 */
  19
  20/*
  21 * Driver: dt9812
  22 * Description: Data Translation DT9812 USB module
  23 * Devices: [Data Translation] DT9812 (dt9812)
  24 * Author: anders.blomdell@control.lth.se (Anders Blomdell)
  25 * Status: in development
  26 * Updated: Sun Nov 20 20:18:34 EST 2005
  27 *
  28 * This driver works, but bulk transfers not implemented. Might be a
  29 * starting point for someone else. I found out too late that USB has
  30 * too high latencies (>1 ms) for my needs.
  31 */
  32
  33/*
  34 * Nota Bene:
  35 *   1. All writes to command pipe has to be 32 bytes (ISP1181B SHRTP=0 ?)
  36 *   2. The DDK source (as of sep 2005) is in error regarding the
  37 *      input MUX bits (example code says P4, but firmware schematics
  38 *      says P1).
  39 */
  40
  41#include <linux/kernel.h>
  42#include <linux/module.h>
  43#include <linux/errno.h>
  44#include <linux/uaccess.h>
  45
  46#include "../comedi_usb.h"
  47
  48#define DT9812_DIAGS_BOARD_INFO_ADDR    0xFBFF
  49#define DT9812_MAX_WRITE_CMD_PIPE_SIZE  32
  50#define DT9812_MAX_READ_CMD_PIPE_SIZE   32
  51
  52/* usb_bulk_msg() timout in milliseconds */
  53#define DT9812_USB_TIMEOUT              1000
  54
  55/*
  56 * See Silican Laboratories C8051F020/1/2/3 manual
  57 */
  58#define F020_SFR_P4                     0x84
  59#define F020_SFR_P1                     0x90
  60#define F020_SFR_P2                     0xa0
  61#define F020_SFR_P3                     0xb0
  62#define F020_SFR_AMX0CF                 0xba
  63#define F020_SFR_AMX0SL                 0xbb
  64#define F020_SFR_ADC0CF                 0xbc
  65#define F020_SFR_ADC0L                  0xbe
  66#define F020_SFR_ADC0H                  0xbf
  67#define F020_SFR_DAC0L                  0xd2
  68#define F020_SFR_DAC0H                  0xd3
  69#define F020_SFR_DAC0CN                 0xd4
  70#define F020_SFR_DAC1L                  0xd5
  71#define F020_SFR_DAC1H                  0xd6
  72#define F020_SFR_DAC1CN                 0xd7
  73#define F020_SFR_ADC0CN                 0xe8
  74
  75#define F020_MASK_ADC0CF_AMP0GN0        0x01
  76#define F020_MASK_ADC0CF_AMP0GN1        0x02
  77#define F020_MASK_ADC0CF_AMP0GN2        0x04
  78
  79#define F020_MASK_ADC0CN_AD0EN          0x80
  80#define F020_MASK_ADC0CN_AD0INT         0x20
  81#define F020_MASK_ADC0CN_AD0BUSY        0x10
  82
  83#define F020_MASK_DACXCN_DACXEN         0x80
  84
  85enum {
  86                                        /* A/D  D/A  DI  DO  CT */
  87        DT9812_DEVID_DT9812_10,         /*  8    2   8   8   1  +/- 10V */
  88        DT9812_DEVID_DT9812_2PT5,       /*  8    2   8   8   1  0-2.44V */
  89};
  90
  91enum dt9812_gain {
  92        DT9812_GAIN_0PT25 = 1,
  93        DT9812_GAIN_0PT5 = 2,
  94        DT9812_GAIN_1 = 4,
  95        DT9812_GAIN_2 = 8,
  96        DT9812_GAIN_4 = 16,
  97        DT9812_GAIN_8 = 32,
  98        DT9812_GAIN_16 = 64,
  99};
 100
 101enum {
 102        DT9812_LEAST_USB_FIRMWARE_CMD_CODE = 0,
 103        /* Write Flash memory */
 104        DT9812_W_FLASH_DATA = 0,
 105        /* Read Flash memory misc config info */
 106        DT9812_R_FLASH_DATA = 1,
 107
 108        /*
 109         * Register read/write commands for processor
 110         */
 111
 112        /* Read a single byte of USB memory */
 113        DT9812_R_SINGLE_BYTE_REG = 2,
 114        /* Write a single byte of USB memory */
 115        DT9812_W_SINGLE_BYTE_REG = 3,
 116        /* Multiple Reads of USB memory */
 117        DT9812_R_MULTI_BYTE_REG = 4,
 118        /* Multiple Writes of USB memory */
 119        DT9812_W_MULTI_BYTE_REG = 5,
 120        /* Read, (AND) with mask, OR value, then write (single) */
 121        DT9812_RMW_SINGLE_BYTE_REG = 6,
 122        /* Read, (AND) with mask, OR value, then write (multiple) */
 123        DT9812_RMW_MULTI_BYTE_REG = 7,
 124
 125        /*
 126         * Register read/write commands for SMBus
 127         */
 128
 129        /* Read a single byte of SMBus */
 130        DT9812_R_SINGLE_BYTE_SMBUS = 8,
 131        /* Write a single byte of SMBus */
 132        DT9812_W_SINGLE_BYTE_SMBUS = 9,
 133        /* Multiple Reads of SMBus */
 134        DT9812_R_MULTI_BYTE_SMBUS = 10,
 135        /* Multiple Writes of SMBus */
 136        DT9812_W_MULTI_BYTE_SMBUS = 11,
 137
 138        /*
 139         * Register read/write commands for a device
 140         */
 141
 142        /* Read a single byte of a device */
 143        DT9812_R_SINGLE_BYTE_DEV = 12,
 144        /* Write a single byte of a device */
 145        DT9812_W_SINGLE_BYTE_DEV = 13,
 146        /* Multiple Reads of a device */
 147        DT9812_R_MULTI_BYTE_DEV = 14,
 148        /* Multiple Writes of a device */
 149        DT9812_W_MULTI_BYTE_DEV = 15,
 150
 151        /* Not sure if we'll need this */
 152        DT9812_W_DAC_THRESHOLD = 16,
 153
 154        /* Set interrupt on change mask */
 155        DT9812_W_INT_ON_CHANGE_MASK = 17,
 156
 157        /* Write (or Clear) the CGL for the ADC */
 158        DT9812_W_CGL = 18,
 159        /* Multiple Reads of USB memory */
 160        DT9812_R_MULTI_BYTE_USBMEM = 19,
 161        /* Multiple Writes to USB memory */
 162        DT9812_W_MULTI_BYTE_USBMEM = 20,
 163
 164        /* Issue a start command to a given subsystem */
 165        DT9812_START_SUBSYSTEM = 21,
 166        /* Issue a stop command to a given subsystem */
 167        DT9812_STOP_SUBSYSTEM = 22,
 168
 169        /* calibrate the board using CAL_POT_CMD */
 170        DT9812_CALIBRATE_POT = 23,
 171        /* set the DAC FIFO size */
 172        DT9812_W_DAC_FIFO_SIZE = 24,
 173        /* Write or Clear the CGL for the DAC */
 174        DT9812_W_CGL_DAC = 25,
 175        /* Read a single value from a subsystem */
 176        DT9812_R_SINGLE_VALUE_CMD = 26,
 177        /* Write a single value to a subsystem */
 178        DT9812_W_SINGLE_VALUE_CMD = 27,
 179        /* Valid DT9812_USB_FIRMWARE_CMD_CODE's will be less than this number */
 180        DT9812_MAX_USB_FIRMWARE_CMD_CODE,
 181};
 182
 183struct dt9812_flash_data {
 184        __le16 numbytes;
 185        __le16 address;
 186};
 187
 188#define DT9812_MAX_NUM_MULTI_BYTE_RDS  \
 189        ((DT9812_MAX_WRITE_CMD_PIPE_SIZE - 4 - 1) / sizeof(u8))
 190
 191struct dt9812_read_multi {
 192        u8 count;
 193        u8 address[DT9812_MAX_NUM_MULTI_BYTE_RDS];
 194};
 195
 196struct dt9812_write_byte {
 197        u8 address;
 198        u8 value;
 199};
 200
 201#define DT9812_MAX_NUM_MULTI_BYTE_WRTS  \
 202        ((DT9812_MAX_WRITE_CMD_PIPE_SIZE - 4 - 1) / \
 203         sizeof(struct dt9812_write_byte))
 204
 205struct dt9812_write_multi {
 206        u8 count;
 207        struct dt9812_write_byte write[DT9812_MAX_NUM_MULTI_BYTE_WRTS];
 208};
 209
 210struct dt9812_rmw_byte {
 211        u8 address;
 212        u8 and_mask;
 213        u8 or_value;
 214};
 215
 216#define DT9812_MAX_NUM_MULTI_BYTE_RMWS  \
 217        ((DT9812_MAX_WRITE_CMD_PIPE_SIZE - 4 - 1) / \
 218         sizeof(struct dt9812_rmw_byte))
 219
 220struct dt9812_rmw_multi {
 221        u8 count;
 222        struct dt9812_rmw_byte rmw[DT9812_MAX_NUM_MULTI_BYTE_RMWS];
 223};
 224
 225struct dt9812_usb_cmd {
 226        __le32 cmd;
 227        union {
 228                struct dt9812_flash_data flash_data_info;
 229                struct dt9812_read_multi read_multi_info;
 230                struct dt9812_write_multi write_multi_info;
 231                struct dt9812_rmw_multi rmw_multi_info;
 232        } u;
 233};
 234
 235struct dt9812_private {
 236        struct mutex mut;
 237        struct {
 238                __u8 addr;
 239                size_t size;
 240        } cmd_wr, cmd_rd;
 241        u16 device;
 242};
 243
 244static int dt9812_read_info(struct comedi_device *dev,
 245                            int offset, void *buf, size_t buf_size)
 246{
 247        struct usb_device *usb = comedi_to_usb_dev(dev);
 248        struct dt9812_private *devpriv = dev->private;
 249        struct dt9812_usb_cmd cmd;
 250        int count, ret;
 251
 252        cmd.cmd = cpu_to_le32(DT9812_R_FLASH_DATA);
 253        cmd.u.flash_data_info.address =
 254            cpu_to_le16(DT9812_DIAGS_BOARD_INFO_ADDR + offset);
 255        cmd.u.flash_data_info.numbytes = cpu_to_le16(buf_size);
 256
 257        /* DT9812 only responds to 32 byte writes!! */
 258        ret = usb_bulk_msg(usb, usb_sndbulkpipe(usb, devpriv->cmd_wr.addr),
 259                           &cmd, 32, &count, DT9812_USB_TIMEOUT);
 260        if (ret)
 261                return ret;
 262
 263        return usb_bulk_msg(usb, usb_rcvbulkpipe(usb, devpriv->cmd_rd.addr),
 264                            buf, buf_size, &count, DT9812_USB_TIMEOUT);
 265}
 266
 267static int dt9812_read_multiple_registers(struct comedi_device *dev,
 268                                          int reg_count, u8 *address,
 269                                          u8 *value)
 270{
 271        struct usb_device *usb = comedi_to_usb_dev(dev);
 272        struct dt9812_private *devpriv = dev->private;
 273        struct dt9812_usb_cmd cmd;
 274        int i, count, ret;
 275
 276        cmd.cmd = cpu_to_le32(DT9812_R_MULTI_BYTE_REG);
 277        cmd.u.read_multi_info.count = reg_count;
 278        for (i = 0; i < reg_count; i++)
 279                cmd.u.read_multi_info.address[i] = address[i];
 280
 281        /* DT9812 only responds to 32 byte writes!! */
 282        ret = usb_bulk_msg(usb, usb_sndbulkpipe(usb, devpriv->cmd_wr.addr),
 283                           &cmd, 32, &count, DT9812_USB_TIMEOUT);
 284        if (ret)
 285                return ret;
 286
 287        return usb_bulk_msg(usb, usb_rcvbulkpipe(usb, devpriv->cmd_rd.addr),
 288                            value, reg_count, &count, DT9812_USB_TIMEOUT);
 289}
 290
 291static int dt9812_write_multiple_registers(struct comedi_device *dev,
 292                                           int reg_count, u8 *address,
 293                                           u8 *value)
 294{
 295        struct usb_device *usb = comedi_to_usb_dev(dev);
 296        struct dt9812_private *devpriv = dev->private;
 297        struct dt9812_usb_cmd cmd;
 298        int i, count;
 299
 300        cmd.cmd = cpu_to_le32(DT9812_W_MULTI_BYTE_REG);
 301        cmd.u.read_multi_info.count = reg_count;
 302        for (i = 0; i < reg_count; i++) {
 303                cmd.u.write_multi_info.write[i].address = address[i];
 304                cmd.u.write_multi_info.write[i].value = value[i];
 305        }
 306
 307        /* DT9812 only responds to 32 byte writes!! */
 308        return usb_bulk_msg(usb, usb_sndbulkpipe(usb, devpriv->cmd_wr.addr),
 309                            &cmd, 32, &count, DT9812_USB_TIMEOUT);
 310}
 311
 312static int dt9812_rmw_multiple_registers(struct comedi_device *dev,
 313                                         int reg_count,
 314                                         struct dt9812_rmw_byte *rmw)
 315{
 316        struct usb_device *usb = comedi_to_usb_dev(dev);
 317        struct dt9812_private *devpriv = dev->private;
 318        struct dt9812_usb_cmd cmd;
 319        int i, count;
 320
 321        cmd.cmd = cpu_to_le32(DT9812_RMW_MULTI_BYTE_REG);
 322        cmd.u.rmw_multi_info.count = reg_count;
 323        for (i = 0; i < reg_count; i++)
 324                cmd.u.rmw_multi_info.rmw[i] = rmw[i];
 325
 326        /* DT9812 only responds to 32 byte writes!! */
 327        return usb_bulk_msg(usb, usb_sndbulkpipe(usb, devpriv->cmd_wr.addr),
 328                            &cmd, 32, &count, DT9812_USB_TIMEOUT);
 329}
 330
 331static int dt9812_digital_in(struct comedi_device *dev, u8 *bits)
 332{
 333        struct dt9812_private *devpriv = dev->private;
 334        u8 reg[2] = { F020_SFR_P3, F020_SFR_P1 };
 335        u8 value[2];
 336        int ret;
 337
 338        mutex_lock(&devpriv->mut);
 339        ret = dt9812_read_multiple_registers(dev, 2, reg, value);
 340        if (ret == 0) {
 341                /*
 342                 * bits 0-6 in F020_SFR_P3 are bits 0-6 in the digital
 343                 * input port bit 3 in F020_SFR_P1 is bit 7 in the
 344                 * digital input port
 345                 */
 346                *bits = (value[0] & 0x7f) | ((value[1] & 0x08) << 4);
 347        }
 348        mutex_unlock(&devpriv->mut);
 349
 350        return ret;
 351}
 352
 353static int dt9812_digital_out(struct comedi_device *dev, u8 bits)
 354{
 355        struct dt9812_private *devpriv = dev->private;
 356        u8 reg[1] = { F020_SFR_P2 };
 357        u8 value[1] = { bits };
 358        int ret;
 359
 360        mutex_lock(&devpriv->mut);
 361        ret = dt9812_write_multiple_registers(dev, 1, reg, value);
 362        mutex_unlock(&devpriv->mut);
 363
 364        return ret;
 365}
 366
 367static void dt9812_configure_mux(struct comedi_device *dev,
 368                                 struct dt9812_rmw_byte *rmw, int channel)
 369{
 370        struct dt9812_private *devpriv = dev->private;
 371
 372        if (devpriv->device == DT9812_DEVID_DT9812_10) {
 373                /* In the DT9812/10V MUX is selected by P1.5-7 */
 374                rmw->address = F020_SFR_P1;
 375                rmw->and_mask = 0xe0;
 376                rmw->or_value = channel << 5;
 377        } else {
 378                /* In the DT9812/2.5V, internal mux is selected by bits 0:2 */
 379                rmw->address = F020_SFR_AMX0SL;
 380                rmw->and_mask = 0xff;
 381                rmw->or_value = channel & 0x07;
 382        }
 383}
 384
 385static void dt9812_configure_gain(struct comedi_device *dev,
 386                                  struct dt9812_rmw_byte *rmw,
 387                                  enum dt9812_gain gain)
 388{
 389        struct dt9812_private *devpriv = dev->private;
 390
 391        /* In the DT9812/10V, there is an external gain of 0.5 */
 392        if (devpriv->device == DT9812_DEVID_DT9812_10)
 393                gain <<= 1;
 394
 395        rmw->address = F020_SFR_ADC0CF;
 396        rmw->and_mask = F020_MASK_ADC0CF_AMP0GN2 |
 397                        F020_MASK_ADC0CF_AMP0GN1 |
 398                        F020_MASK_ADC0CF_AMP0GN0;
 399
 400        switch (gain) {
 401                /*
 402                 * 000 -> Gain =  1
 403                 * 001 -> Gain =  2
 404                 * 010 -> Gain =  4
 405                 * 011 -> Gain =  8
 406                 * 10x -> Gain = 16
 407                 * 11x -> Gain =  0.5
 408                 */
 409        case DT9812_GAIN_0PT5:
 410                rmw->or_value = F020_MASK_ADC0CF_AMP0GN2 |
 411                                F020_MASK_ADC0CF_AMP0GN1;
 412                break;
 413        default:
 414                /* this should never happen, just use a gain of 1 */
 415        case DT9812_GAIN_1:
 416                rmw->or_value = 0x00;
 417                break;
 418        case DT9812_GAIN_2:
 419                rmw->or_value = F020_MASK_ADC0CF_AMP0GN0;
 420                break;
 421        case DT9812_GAIN_4:
 422                rmw->or_value = F020_MASK_ADC0CF_AMP0GN1;
 423                break;
 424        case DT9812_GAIN_8:
 425                rmw->or_value = F020_MASK_ADC0CF_AMP0GN1 |
 426                                F020_MASK_ADC0CF_AMP0GN0;
 427                break;
 428        case DT9812_GAIN_16:
 429                rmw->or_value = F020_MASK_ADC0CF_AMP0GN2;
 430                break;
 431        }
 432}
 433
 434static int dt9812_analog_in(struct comedi_device *dev,
 435                            int channel, u16 *value, enum dt9812_gain gain)
 436{
 437        struct dt9812_private *devpriv = dev->private;
 438        struct dt9812_rmw_byte rmw[3];
 439        u8 reg[3] = {
 440                F020_SFR_ADC0CN,
 441                F020_SFR_ADC0H,
 442                F020_SFR_ADC0L
 443        };
 444        u8 val[3];
 445        int ret;
 446
 447        mutex_lock(&devpriv->mut);
 448
 449        /* 1 select the gain */
 450        dt9812_configure_gain(dev, &rmw[0], gain);
 451
 452        /* 2 set the MUX to select the channel */
 453        dt9812_configure_mux(dev, &rmw[1], channel);
 454
 455        /* 3 start conversion */
 456        rmw[2].address = F020_SFR_ADC0CN;
 457        rmw[2].and_mask = 0xff;
 458        rmw[2].or_value = F020_MASK_ADC0CN_AD0EN | F020_MASK_ADC0CN_AD0BUSY;
 459
 460        ret = dt9812_rmw_multiple_registers(dev, 3, rmw);
 461        if (ret)
 462                goto exit;
 463
 464        /* read the status and ADC */
 465        ret = dt9812_read_multiple_registers(dev, 3, reg, val);
 466        if (ret)
 467                goto exit;
 468
 469        /*
 470         * An ADC conversion takes 16 SAR clocks cycles, i.e. about 9us.
 471         * Therefore, between the instant that AD0BUSY was set via
 472         * dt9812_rmw_multiple_registers and the read of AD0BUSY via
 473         * dt9812_read_multiple_registers, the conversion should be complete
 474         * since these two operations require two USB transactions each taking
 475         * at least a millisecond to complete.  However, lets make sure that
 476         * conversion is finished.
 477         */
 478        if ((val[0] & (F020_MASK_ADC0CN_AD0INT | F020_MASK_ADC0CN_AD0BUSY)) ==
 479            F020_MASK_ADC0CN_AD0INT) {
 480                switch (devpriv->device) {
 481                case DT9812_DEVID_DT9812_10:
 482                        /*
 483                         * For DT9812-10V the personality module set the
 484                         * encoding to 2's complement. Hence, convert it before
 485                         * returning it
 486                         */
 487                        *value = ((val[1] << 8) | val[2]) + 0x800;
 488                        break;
 489                case DT9812_DEVID_DT9812_2PT5:
 490                        *value = (val[1] << 8) | val[2];
 491                        break;
 492                }
 493        }
 494
 495exit:
 496        mutex_unlock(&devpriv->mut);
 497
 498        return ret;
 499}
 500
 501static int dt9812_analog_out(struct comedi_device *dev, int channel, u16 value)
 502{
 503        struct dt9812_private *devpriv = dev->private;
 504        struct dt9812_rmw_byte rmw[3];
 505        int ret;
 506
 507        mutex_lock(&devpriv->mut);
 508
 509        switch (channel) {
 510        case 0:
 511                /* 1. Set DAC mode */
 512                rmw[0].address = F020_SFR_DAC0CN;
 513                rmw[0].and_mask = 0xff;
 514                rmw[0].or_value = F020_MASK_DACXCN_DACXEN;
 515
 516                /* 2. load lsb of DAC value first */
 517                rmw[1].address = F020_SFR_DAC0L;
 518                rmw[1].and_mask = 0xff;
 519                rmw[1].or_value = value & 0xff;
 520
 521                /* 3. load msb of DAC value next to latch the 12-bit value */
 522                rmw[2].address = F020_SFR_DAC0H;
 523                rmw[2].and_mask = 0xff;
 524                rmw[2].or_value = (value >> 8) & 0xf;
 525                break;
 526
 527        case 1:
 528                /* 1. Set DAC mode */
 529                rmw[0].address = F020_SFR_DAC1CN;
 530                rmw[0].and_mask = 0xff;
 531                rmw[0].or_value = F020_MASK_DACXCN_DACXEN;
 532
 533                /* 2. load lsb of DAC value first */
 534                rmw[1].address = F020_SFR_DAC1L;
 535                rmw[1].and_mask = 0xff;
 536                rmw[1].or_value = value & 0xff;
 537
 538                /* 3. load msb of DAC value next to latch the 12-bit value */
 539                rmw[2].address = F020_SFR_DAC1H;
 540                rmw[2].and_mask = 0xff;
 541                rmw[2].or_value = (value >> 8) & 0xf;
 542                break;
 543        }
 544        ret = dt9812_rmw_multiple_registers(dev, 3, rmw);
 545
 546        mutex_unlock(&devpriv->mut);
 547
 548        return ret;
 549}
 550
 551static int dt9812_di_insn_bits(struct comedi_device *dev,
 552                               struct comedi_subdevice *s,
 553                               struct comedi_insn *insn,
 554                               unsigned int *data)
 555{
 556        u8 bits = 0;
 557        int ret;
 558
 559        ret = dt9812_digital_in(dev, &bits);
 560        if (ret)
 561                return ret;
 562
 563        data[1] = bits;
 564
 565        return insn->n;
 566}
 567
 568static int dt9812_do_insn_bits(struct comedi_device *dev,
 569                               struct comedi_subdevice *s,
 570                               struct comedi_insn *insn,
 571                               unsigned int *data)
 572{
 573        if (comedi_dio_update_state(s, data))
 574                dt9812_digital_out(dev, s->state);
 575
 576        data[1] = s->state;
 577
 578        return insn->n;
 579}
 580
 581static int dt9812_ai_insn_read(struct comedi_device *dev,
 582                               struct comedi_subdevice *s,
 583                               struct comedi_insn *insn,
 584                               unsigned int *data)
 585{
 586        unsigned int chan = CR_CHAN(insn->chanspec);
 587        u16 val = 0;
 588        int ret;
 589        int i;
 590
 591        for (i = 0; i < insn->n; i++) {
 592                ret = dt9812_analog_in(dev, chan, &val, DT9812_GAIN_1);
 593                if (ret)
 594                        return ret;
 595                data[i] = val;
 596        }
 597
 598        return insn->n;
 599}
 600
 601static int dt9812_ao_insn_read(struct comedi_device *dev,
 602                               struct comedi_subdevice *s,
 603                               struct comedi_insn *insn,
 604                               unsigned int *data)
 605{
 606        struct dt9812_private *devpriv = dev->private;
 607        int ret;
 608
 609        mutex_lock(&devpriv->mut);
 610        ret = comedi_readback_insn_read(dev, s, insn, data);
 611        mutex_unlock(&devpriv->mut);
 612
 613        return ret;
 614}
 615
 616static int dt9812_ao_insn_write(struct comedi_device *dev,
 617                                struct comedi_subdevice *s,
 618                                struct comedi_insn *insn,
 619                                unsigned int *data)
 620{
 621        unsigned int chan = CR_CHAN(insn->chanspec);
 622        int i;
 623
 624        for (i = 0; i < insn->n; i++) {
 625                unsigned int val = data[i];
 626                int ret;
 627
 628                ret = dt9812_analog_out(dev, chan, val);
 629                if (ret)
 630                        return ret;
 631
 632                s->readback[chan] = val;
 633        }
 634
 635        return insn->n;
 636}
 637
 638static int dt9812_find_endpoints(struct comedi_device *dev)
 639{
 640        struct usb_interface *intf = comedi_to_usb_interface(dev);
 641        struct usb_host_interface *host = intf->cur_altsetting;
 642        struct dt9812_private *devpriv = dev->private;
 643        struct usb_endpoint_descriptor *ep;
 644        int i;
 645
 646        if (host->desc.bNumEndpoints != 5) {
 647                dev_err(dev->class_dev, "Wrong number of endpoints\n");
 648                return -ENODEV;
 649        }
 650
 651        for (i = 0; i < host->desc.bNumEndpoints; ++i) {
 652                int dir = -1;
 653
 654                ep = &host->endpoint[i].desc;
 655                switch (i) {
 656                case 0:
 657                        /* unused message pipe */
 658                        dir = USB_DIR_IN;
 659                        break;
 660                case 1:
 661                        dir = USB_DIR_OUT;
 662                        devpriv->cmd_wr.addr = ep->bEndpointAddress;
 663                        devpriv->cmd_wr.size = le16_to_cpu(ep->wMaxPacketSize);
 664                        break;
 665                case 2:
 666                        dir = USB_DIR_IN;
 667                        devpriv->cmd_rd.addr = ep->bEndpointAddress;
 668                        devpriv->cmd_rd.size = le16_to_cpu(ep->wMaxPacketSize);
 669                        break;
 670                case 3:
 671                        /* unused write stream */
 672                        dir = USB_DIR_OUT;
 673                        break;
 674                case 4:
 675                        /* unused read stream */
 676                        dir = USB_DIR_IN;
 677                        break;
 678                }
 679                if ((ep->bEndpointAddress & USB_DIR_IN) != dir) {
 680                        dev_err(dev->class_dev,
 681                                "Endpoint has wrong direction\n");
 682                        return -ENODEV;
 683                }
 684        }
 685        return 0;
 686}
 687
 688static int dt9812_reset_device(struct comedi_device *dev)
 689{
 690        struct usb_device *usb = comedi_to_usb_dev(dev);
 691        struct dt9812_private *devpriv = dev->private;
 692        u32 serial;
 693        u16 vendor;
 694        u16 product;
 695        u8 tmp8;
 696        __le16 tmp16;
 697        __le32 tmp32;
 698        int ret;
 699        int i;
 700
 701        ret = dt9812_read_info(dev, 0, &tmp8, sizeof(tmp8));
 702        if (ret) {
 703                /*
 704                 * Seems like a configuration reset is necessary if driver is
 705                 * reloaded while device is attached
 706                 */
 707                usb_reset_configuration(usb);
 708                for (i = 0; i < 10; i++) {
 709                        ret = dt9812_read_info(dev, 1, &tmp8, sizeof(tmp8));
 710                        if (ret == 0)
 711                                break;
 712                }
 713                if (ret) {
 714                        dev_err(dev->class_dev,
 715                                "unable to reset configuration\n");
 716                        return ret;
 717                }
 718        }
 719
 720        ret = dt9812_read_info(dev, 1, &tmp16, sizeof(tmp16));
 721        if (ret) {
 722                dev_err(dev->class_dev, "failed to read vendor id\n");
 723                return ret;
 724        }
 725        vendor = le16_to_cpu(tmp16);
 726
 727        ret = dt9812_read_info(dev, 3, &tmp16, sizeof(tmp16));
 728        if (ret) {
 729                dev_err(dev->class_dev, "failed to read product id\n");
 730                return ret;
 731        }
 732        product = le16_to_cpu(tmp16);
 733
 734        ret = dt9812_read_info(dev, 5, &tmp16, sizeof(tmp16));
 735        if (ret) {
 736                dev_err(dev->class_dev, "failed to read device id\n");
 737                return ret;
 738        }
 739        devpriv->device = le16_to_cpu(tmp16);
 740
 741        ret = dt9812_read_info(dev, 7, &tmp32, sizeof(tmp32));
 742        if (ret) {
 743                dev_err(dev->class_dev, "failed to read serial number\n");
 744                return ret;
 745        }
 746        serial = le32_to_cpu(tmp32);
 747
 748        /* let the user know what node this device is now attached to */
 749        dev_info(dev->class_dev, "USB DT9812 (%4.4x.%4.4x.%4.4x) #0x%8.8x\n",
 750                 vendor, product, devpriv->device, serial);
 751
 752        if (devpriv->device != DT9812_DEVID_DT9812_10 &&
 753            devpriv->device != DT9812_DEVID_DT9812_2PT5) {
 754                dev_err(dev->class_dev, "Unsupported device!\n");
 755                return -EINVAL;
 756        }
 757
 758        return 0;
 759}
 760
 761static int dt9812_auto_attach(struct comedi_device *dev,
 762                              unsigned long context)
 763{
 764        struct usb_interface *intf = comedi_to_usb_interface(dev);
 765        struct dt9812_private *devpriv;
 766        struct comedi_subdevice *s;
 767        bool is_unipolar;
 768        int ret;
 769        int i;
 770
 771        devpriv = comedi_alloc_devpriv(dev, sizeof(*devpriv));
 772        if (!devpriv)
 773                return -ENOMEM;
 774
 775        mutex_init(&devpriv->mut);
 776        usb_set_intfdata(intf, devpriv);
 777
 778        ret = dt9812_find_endpoints(dev);
 779        if (ret)
 780                return ret;
 781
 782        ret = dt9812_reset_device(dev);
 783        if (ret)
 784                return ret;
 785
 786        is_unipolar = (devpriv->device == DT9812_DEVID_DT9812_2PT5);
 787
 788        ret = comedi_alloc_subdevices(dev, 4);
 789        if (ret)
 790                return ret;
 791
 792        /* Digital Input subdevice */
 793        s = &dev->subdevices[0];
 794        s->type         = COMEDI_SUBD_DI;
 795        s->subdev_flags = SDF_READABLE;
 796        s->n_chan       = 8;
 797        s->maxdata      = 1;
 798        s->range_table  = &range_digital;
 799        s->insn_bits    = dt9812_di_insn_bits;
 800
 801        /* Digital Output subdevice */
 802        s = &dev->subdevices[1];
 803        s->type         = COMEDI_SUBD_DO;
 804        s->subdev_flags = SDF_WRITABLE;
 805        s->n_chan       = 8;
 806        s->maxdata      = 1;
 807        s->range_table  = &range_digital;
 808        s->insn_bits    = dt9812_do_insn_bits;
 809
 810        /* Analog Input subdevice */
 811        s = &dev->subdevices[2];
 812        s->type         = COMEDI_SUBD_AI;
 813        s->subdev_flags = SDF_READABLE | SDF_GROUND;
 814        s->n_chan       = 8;
 815        s->maxdata      = 0x0fff;
 816        s->range_table  = is_unipolar ? &range_unipolar2_5 : &range_bipolar10;
 817        s->insn_read    = dt9812_ai_insn_read;
 818
 819        /* Analog Output subdevice */
 820        s = &dev->subdevices[3];
 821        s->type         = COMEDI_SUBD_AO;
 822        s->subdev_flags = SDF_WRITABLE;
 823        s->n_chan       = 2;
 824        s->maxdata      = 0x0fff;
 825        s->range_table  = is_unipolar ? &range_unipolar2_5 : &range_bipolar10;
 826        s->insn_write   = dt9812_ao_insn_write;
 827        s->insn_read    = dt9812_ao_insn_read;
 828
 829        ret = comedi_alloc_subdev_readback(s);
 830        if (ret)
 831                return ret;
 832
 833        for (i = 0; i < s->n_chan; i++)
 834                s->readback[i] = is_unipolar ? 0x0000 : 0x0800;
 835
 836        return 0;
 837}
 838
 839static void dt9812_detach(struct comedi_device *dev)
 840{
 841        struct usb_interface *intf = comedi_to_usb_interface(dev);
 842        struct dt9812_private *devpriv = dev->private;
 843
 844        if (!devpriv)
 845                return;
 846
 847        mutex_lock(&devpriv->mut);
 848
 849        usb_set_intfdata(intf, NULL);
 850
 851        mutex_unlock(&devpriv->mut);
 852}
 853
 854static struct comedi_driver dt9812_driver = {
 855        .driver_name    = "dt9812",
 856        .module         = THIS_MODULE,
 857        .auto_attach    = dt9812_auto_attach,
 858        .detach         = dt9812_detach,
 859};
 860
 861static int dt9812_usb_probe(struct usb_interface *intf,
 862                            const struct usb_device_id *id)
 863{
 864        return comedi_usb_auto_config(intf, &dt9812_driver, id->driver_info);
 865}
 866
 867static const struct usb_device_id dt9812_usb_table[] = {
 868        { USB_DEVICE(0x0867, 0x9812) },
 869        { }
 870};
 871MODULE_DEVICE_TABLE(usb, dt9812_usb_table);
 872
 873static struct usb_driver dt9812_usb_driver = {
 874        .name           = "dt9812",
 875        .id_table       = dt9812_usb_table,
 876        .probe          = dt9812_usb_probe,
 877        .disconnect     = comedi_usb_auto_unconfig,
 878};
 879module_comedi_usb_driver(dt9812_driver, dt9812_usb_driver);
 880
 881MODULE_AUTHOR("Anders Blomdell <anders.blomdell@control.lth.se>");
 882MODULE_DESCRIPTION("Comedi DT9812 driver");
 883MODULE_LICENSE("GPL");
 884