linux/drivers/staging/rts5139/rts51x_fop.c
<<
>>
Prefs
   1/* Driver for Realtek RTS51xx USB card reader
   2 *
   3 * Copyright(c) 2009 Realtek Semiconductor Corp. All rights reserved.
   4 *
   5 * This program is free software; you can redistribute it and/or modify it
   6 * under the terms of the GNU General Public License as published by the
   7 * Free Software Foundation; either version 2, or (at your option) any
   8 * later version.
   9 *
  10 * This program is distributed in the hope that it will be useful, but
  11 * WITHOUT ANY WARRANTY; without even the implied warranty of
  12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  13 * General Public License for more details.
  14 *
  15 * You should have received a copy of the GNU General Public License along
  16 * with this program; if not, see <http://www.gnu.org/licenses/>.
  17 *
  18 * Author:
  19 *   wwang (wei_wang@realsil.com.cn)
  20 *   No. 450, Shenhu Road, Suzhou Industry Park, Suzhou, China
  21 * Maintainer:
  22 *   Edwin Rong (edwin_rong@realsil.com.cn)
  23 *   No. 450, Shenhu Road, Suzhou Industry Park, Suzhou, China
  24 */
  25
  26#include "rts51x.h"
  27
  28#ifdef SUPPORT_FILE_OP
  29
  30#include <linux/types.h>
  31#include <linux/stat.h>
  32#include <linux/kref.h>
  33#include <linux/slab.h>
  34
  35#include "rts51x_chip.h"
  36#include "rts51x_card.h"
  37#include "rts51x_fop.h"
  38#include "sd_cprm.h"
  39
  40#define RTS5139_IOC_MAGIC               0x39
  41
  42#define RTS5139_IOC_SD_DIRECT           _IOWR(RTS5139_IOC_MAGIC, 0xA0, int)
  43#define RTS5139_IOC_SD_GET_RSP          _IOWR(RTS5139_IOC_MAGIC, 0xA1, int)
  44
  45static int rts51x_sd_direct_cmnd(struct rts51x_chip *chip,
  46                                 struct sd_direct_cmnd *cmnd)
  47{
  48        int retval;
  49        u8 dir, cmd12, standby, acmd, cmd_idx, rsp_code;
  50        u8 *buf;
  51        u32 arg, len;
  52
  53        dir = (cmnd->cmnd[0] >> 3) & 0x03;
  54        cmd12 = (cmnd->cmnd[0] >> 2) & 0x01;
  55        standby = (cmnd->cmnd[0] >> 1) & 0x01;
  56        acmd = cmnd->cmnd[0] & 0x01;
  57        cmd_idx = cmnd->cmnd[1];
  58        arg = ((u32) (cmnd->cmnd[2]) << 24) | ((u32) (cmnd->cmnd[3]) << 16) |
  59            ((u32) (cmnd->cmnd[4]) << 8) | cmnd->cmnd[5];
  60        len =
  61            ((u32) (cmnd->cmnd[6]) << 16) | ((u32) (cmnd->cmnd[7]) << 8) |
  62            cmnd->cmnd[8];
  63        rsp_code = cmnd->cmnd[9];
  64
  65        if (dir) {
  66                if (!cmnd->buf || (cmnd->buf_len < len))
  67                        TRACE_RET(chip, STATUS_FAIL);
  68        }
  69
  70        switch (dir) {
  71        case 0:
  72                /* No data */
  73                retval = ext_rts51x_sd_execute_no_data(chip, chip->card2lun[SD_CARD],
  74                                                cmd_idx, standby, acmd,
  75                                                rsp_code, arg);
  76                if (retval != TRANSPORT_GOOD)
  77                        TRACE_RET(chip, STATUS_FAIL);
  78                break;
  79
  80        case 1:
  81                /* Read from card */
  82                buf = kzalloc(cmnd->buf_len, GFP_KERNEL);
  83                if (!buf)
  84                        TRACE_RET(chip, STATUS_NOMEM);
  85
  86                retval = ext_rts51x_sd_execute_read_data(chip, chip->card2lun[SD_CARD],
  87                                                  cmd_idx, cmd12, standby, acmd,
  88                                                  rsp_code, arg, len, buf,
  89                                                  cmnd->buf_len, 0);
  90                if (retval != TRANSPORT_GOOD) {
  91                        kfree(buf);
  92                        TRACE_RET(chip, STATUS_FAIL);
  93                }
  94
  95                retval =
  96                    copy_to_user((void *)cmnd->buf, (void *)buf, cmnd->buf_len);
  97                if (retval) {
  98                        kfree(buf);
  99                        TRACE_RET(chip, STATUS_NOMEM);
 100                }
 101
 102                kfree(buf);
 103                break;
 104
 105        case 2:
 106                /* Write to card */
 107                buf = kmalloc(cmnd->buf_len, GFP_KERNEL);
 108                if (!buf)
 109                        TRACE_RET(chip, STATUS_NOMEM);
 110
 111                retval =
 112                    copy_from_user((void *)buf, (void *)cmnd->buf,
 113                                   cmnd->buf_len);
 114                if (retval) {
 115                        kfree(buf);
 116                        TRACE_RET(chip, STATUS_NOMEM);
 117                }
 118
 119                retval =
 120                    ext_rts51x_sd_execute_write_data(chip, chip->card2lun[SD_CARD],
 121                                              cmd_idx, cmd12, standby, acmd,
 122                                              rsp_code, arg, len, buf,
 123                                              cmnd->buf_len, 0);
 124                if (retval != TRANSPORT_GOOD) {
 125                        kfree(buf);
 126                        TRACE_RET(chip, STATUS_FAIL);
 127                }
 128
 129                kfree(buf);
 130
 131                break;
 132
 133        default:
 134                TRACE_RET(chip, STATUS_FAIL);
 135        }
 136
 137        return STATUS_SUCCESS;
 138}
 139
 140static int rts51x_sd_get_rsp(struct rts51x_chip *chip, struct sd_rsp *rsp)
 141{
 142        struct sd_info *sd_card = &(chip->sd_card);
 143        int count = 0, retval;
 144
 145        if (sd_card->pre_cmd_err) {
 146                sd_card->pre_cmd_err = 0;
 147                TRACE_RET(chip, STATUS_FAIL);
 148        }
 149
 150        if (sd_card->last_rsp_type == SD_RSP_TYPE_R0)
 151                TRACE_RET(chip, STATUS_FAIL);
 152        else if (sd_card->last_rsp_type == SD_RSP_TYPE_R2)
 153                count = (rsp->rsp_len < 17) ? rsp->rsp_len : 17;
 154        else
 155                count = (rsp->rsp_len < 6) ? rsp->rsp_len : 6;
 156
 157        retval = copy_to_user((void *)rsp->rsp, (void *)sd_card->rsp, count);
 158        if (retval)
 159                TRACE_RET(chip, STATUS_NOMEM);
 160
 161        RTS51X_DEBUGP("Response length: %d\n", count);
 162        RTS51X_DEBUGP("Response: 0x%x 0x%x 0x%x 0x%x\n",
 163                       sd_card->rsp[0], sd_card->rsp[1], sd_card->rsp[2],
 164                       sd_card->rsp[3]);
 165
 166        return STATUS_SUCCESS;
 167}
 168
 169int rts51x_open(struct inode *inode, struct file *filp)
 170{
 171        struct rts51x_chip *chip;
 172        struct usb_interface *interface;
 173        int subminor;
 174        int retval = 0;
 175
 176        subminor = iminor(inode);
 177
 178        interface = usb_find_interface(&rts51x_driver, subminor);
 179        if (!interface) {
 180                RTS51X_DEBUGP("%s - error, can't find device for minor %d\n",
 181                               __func__, subminor);
 182                retval = -ENODEV;
 183                goto exit;
 184        }
 185
 186        chip = (struct rts51x_chip *)usb_get_intfdata(interface);
 187        if (!chip) {
 188                RTS51X_DEBUGP("Can't find chip\n");
 189                retval = -ENODEV;
 190                goto exit;
 191        }
 192
 193        /* Increase our reference to the host */
 194        scsi_host_get(rts51x_to_host(chip));
 195
 196        /* lock the device pointers */
 197        mutex_lock(&(chip->usb->dev_mutex));
 198
 199        /* save our object in the file's private structure */
 200        filp->private_data = chip;
 201
 202        /* unlock the device pointers */
 203        mutex_unlock(&chip->usb->dev_mutex);
 204
 205exit:
 206        return retval;
 207}
 208
 209int rts51x_release(struct inode *inode, struct file *filp)
 210{
 211        struct rts51x_chip *chip;
 212
 213        chip = (struct rts51x_chip *)filp->private_data;
 214        if (chip == NULL)
 215                return -ENODEV;
 216
 217        /* Drop our reference to the host; the SCSI core will free it
 218         * (and "chip" along with it) when the refcount becomes 0. */
 219        scsi_host_put(rts51x_to_host(chip));
 220
 221        return 0;
 222}
 223
 224ssize_t rts51x_read(struct file *filp, char __user *buf, size_t count,
 225                    loff_t *f_pos)
 226{
 227        return 0;
 228}
 229
 230ssize_t rts51x_write(struct file *filp, const char __user *buf, size_t count,
 231                     loff_t *f_pos)
 232{
 233        return 0;
 234}
 235
 236long rts51x_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
 237{
 238        struct rts51x_chip *chip;
 239        struct sd_direct_cmnd cmnd;
 240        struct sd_rsp rsp;
 241        int retval = 0;
 242
 243        chip = (struct rts51x_chip *)filp->private_data;
 244        if (chip == NULL)
 245                return -ENODEV;
 246
 247        /* lock the device pointers */
 248        mutex_lock(&(chip->usb->dev_mutex));
 249
 250        switch (cmd) {
 251        case RTS5139_IOC_SD_DIRECT:
 252                retval =
 253                    copy_from_user((void *)&cmnd, (void *)arg,
 254                                   sizeof(struct sd_direct_cmnd));
 255                if (retval) {
 256                        retval = -ENOMEM;
 257                        TRACE_GOTO(chip, exit);
 258                }
 259                retval = rts51x_sd_direct_cmnd(chip, &cmnd);
 260                if (retval != STATUS_SUCCESS) {
 261                        retval = -EIO;
 262                        TRACE_GOTO(chip, exit);
 263                }
 264                break;
 265
 266        case RTS5139_IOC_SD_GET_RSP:
 267                retval =
 268                    copy_from_user((void *)&rsp, (void *)arg,
 269                                   sizeof(struct sd_rsp));
 270                if (retval) {
 271                        retval = -ENOMEM;
 272                        TRACE_GOTO(chip, exit);
 273                }
 274                retval = rts51x_sd_get_rsp(chip, &rsp);
 275                if (retval != STATUS_SUCCESS) {
 276                        retval = -EIO;
 277                        TRACE_GOTO(chip, exit);
 278                }
 279                break;
 280
 281        default:
 282                break;
 283        }
 284
 285exit:
 286        /* unlock the device pointers */
 287        mutex_unlock(&chip->usb->dev_mutex);
 288
 289        return retval;
 290}
 291
 292#endif
 293