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