Linux Kernel  3.7.1
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
rts51x_fop.c
Go to the documentation of this file.
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 ([email protected])
20  * No. 450, Shenhu Road, Suzhou Industry Park, Suzhou, China
21  * Maintainer:
22  * Edwin Rong ([email protected])
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 
45 static 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_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_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 =
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 
140 static 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 
169 int 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 
205 exit:
206  return retval;
207 }
208 
209 int 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 
224 ssize_t rts51x_read(struct file *filp, char __user *buf, size_t count,
225  loff_t *f_pos)
226 {
227  return 0;
228 }
229 
230 ssize_t rts51x_write(struct file *filp, const char __user *buf, size_t count,
231  loff_t *f_pos)
232 {
233  return 0;
234 }
235 
236 long 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) {
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 
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 
285 exit:
286  /* unlock the device pointers */
287  mutex_unlock(&chip->usb->dev_mutex);
288 
289  return retval;
290 }
291 
292 #endif