blob: 6eaebb6223c9abb10a360bba6c6375b051ba74d7 [file] [log] [blame]
edwin_rong1dac4182011-07-19 17:10:35 +08001/* 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#include "rts51x.h"
40
41#define RTS5139_IOC_MAGIC 0x39
42
43#define RTS5139_IOC_SD_DIRECT _IOWR(RTS5139_IOC_MAGIC, 0xA0, int)
44#define RTS5139_IOC_SD_GET_RSP _IOWR(RTS5139_IOC_MAGIC, 0xA1, int)
45
46static int rts51x_sd_direct_cmnd(struct rts51x_chip *chip,
47 struct sd_direct_cmnd *cmnd)
48{
49 int retval;
50 u8 dir, cmd12, standby, acmd, cmd_idx, rsp_code;
51 u8 *buf;
52 u32 arg, len;
53
54 dir = (cmnd->cmnd[0] >> 3) & 0x03;
55 cmd12 = (cmnd->cmnd[0] >> 2) & 0x01;
56 standby = (cmnd->cmnd[0] >> 1) & 0x01;
57 acmd = cmnd->cmnd[0] & 0x01;
58 cmd_idx = cmnd->cmnd[1];
59 arg = ((u32) (cmnd->cmnd[2]) << 24) | ((u32) (cmnd->cmnd[3]) << 16) |
60 ((u32) (cmnd->cmnd[4]) << 8) | cmnd->cmnd[5];
61 len =
62 ((u32) (cmnd->cmnd[6]) << 16) | ((u32) (cmnd->cmnd[7]) << 8) |
63 cmnd->cmnd[8];
64 rsp_code = cmnd->cmnd[9];
65
66 if (dir) {
67 if (!cmnd->buf || (cmnd->buf_len < len))
68 TRACE_RET(chip, STATUS_FAIL);
69 }
70
71 switch (dir) {
72 case 0:
73 /* No data */
74 retval = ext_sd_execute_no_data(chip, chip->card2lun[SD_CARD],
75 cmd_idx, standby, acmd,
76 rsp_code, arg);
77 if (retval != TRANSPORT_GOOD)
78 TRACE_RET(chip, STATUS_FAIL);
79 break;
80
81 case 1:
82 /* Read from card */
83 buf = kmalloc(cmnd->buf_len, GFP_KERNEL);
84 if (!buf)
85 TRACE_RET(chip, STATUS_NOMEM);
86
87 retval = ext_sd_execute_read_data(chip, chip->card2lun[SD_CARD],
88 cmd_idx, cmd12, standby, acmd,
89 rsp_code, arg, len, buf,
90 cmnd->buf_len, 0);
91 if (retval != TRANSPORT_GOOD) {
92 kfree(buf);
93 TRACE_RET(chip, STATUS_FAIL);
94 }
95
96 retval =
97 copy_to_user((void *)cmnd->buf, (void *)buf, cmnd->buf_len);
98 if (retval) {
99 kfree(buf);
100 TRACE_RET(chip, STATUS_NOMEM);
101 }
102
103 kfree(buf);
104 break;
105
106 case 2:
107 /* Write to card */
108 buf = kmalloc(cmnd->buf_len, GFP_KERNEL);
109 if (!buf)
110 TRACE_RET(chip, STATUS_NOMEM);
111
112 retval =
113 copy_from_user((void *)buf, (void *)cmnd->buf,
114 cmnd->buf_len);
115 if (retval) {
116 kfree(buf);
117 TRACE_RET(chip, STATUS_NOMEM);
118 }
119
120 retval =
121 ext_sd_execute_write_data(chip, chip->card2lun[SD_CARD],
122 cmd_idx, cmd12, standby, acmd,
123 rsp_code, arg, len, buf,
124 cmnd->buf_len, 0);
125 if (retval != TRANSPORT_GOOD) {
126 kfree(buf);
127 TRACE_RET(chip, STATUS_FAIL);
128 }
129
130 kfree(buf);
131
132 break;
133
134 default:
135 TRACE_RET(chip, STATUS_FAIL);
136 }
137
138 return STATUS_SUCCESS;
139}
140
141static int rts51x_sd_get_rsp(struct rts51x_chip *chip, struct sd_rsp *rsp)
142{
143 struct sd_info *sd_card = &(chip->sd_card);
144 int count = 0, retval;
145
146 if (sd_card->pre_cmd_err) {
147 sd_card->pre_cmd_err = 0;
148 TRACE_RET(chip, STATUS_FAIL);
149 }
150
151 if (sd_card->last_rsp_type == SD_RSP_TYPE_R0)
152 TRACE_RET(chip, STATUS_FAIL);
153 else if (sd_card->last_rsp_type == SD_RSP_TYPE_R2)
154 count = (rsp->rsp_len < 17) ? rsp->rsp_len : 17;
155 else
156 count = (rsp->rsp_len < 6) ? rsp->rsp_len : 6;
157
158 retval = copy_to_user((void *)rsp->rsp, (void *)sd_card->rsp, count);
159 if (retval)
160 TRACE_RET(chip, STATUS_NOMEM);
161
162 RTS51X_DEBUGP("Response length: %d\n", count);
163 RTS51X_DEBUGP("Response: 0x%x 0x%x 0x%x 0x%x\n",
164 sd_card->rsp[0], sd_card->rsp[1], sd_card->rsp[2],
165 sd_card->rsp[3]);
166
167 return STATUS_SUCCESS;
168}
169
170int rts51x_open(struct inode *inode, struct file *filp)
171{
172 struct rts51x_chip *chip;
173 struct usb_interface *interface;
174 int subminor;
175 int retval = 0;
176
177 subminor = iminor(inode);
178
179 interface = usb_find_interface(&rts51x_driver, subminor);
180 if (!interface) {
181 RTS51X_DEBUGP("%s - error, can't find device for minor %d\n",
182 __func__, subminor);
183 retval = -ENODEV;
184 goto exit;
185 }
186
187 chip = (struct rts51x_chip *)usb_get_intfdata(interface);
188 if (!chip) {
189 RTS51X_DEBUGP("Can't find chip\n");
190 retval = -ENODEV;
191 goto exit;
192 }
193
194 /* Increase our reference to the host */
195 scsi_host_get(rts51x_to_host(chip));
196
197 /* lock the device pointers */
198 mutex_lock(&(chip->usb->dev_mutex));
199
200 /* save our object in the file's private structure */
201 filp->private_data = chip;
202
203 /* unlock the device pointers */
204 mutex_unlock(&chip->usb->dev_mutex);
205
206exit:
207 return retval;
208}
209
210int rts51x_release(struct inode *inode, struct file *filp)
211{
212 struct rts51x_chip *chip;
213
214 chip = (struct rts51x_chip *)filp->private_data;
215 if (chip == NULL)
216 return -ENODEV;
217
218 /* Drop our reference to the host; the SCSI core will free it
219 * (and "chip" along with it) when the refcount becomes 0. */
220 scsi_host_put(rts51x_to_host(chip));
221
222 return 0;
223}
224
225ssize_t rts51x_read(struct file *filp, char __user *buf, size_t count,
226 loff_t *f_pos)
227{
228 return 0;
229}
230
231ssize_t rts51x_write(struct file *filp, const char __user *buf, size_t count,
232 loff_t *f_pos)
233{
234 return 0;
235}
236
237#if 0 /* LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 36) */
238int rts51x_ioctl(struct inode *inode, struct file *filp, unsigned int cmd,
239 unsigned long arg)
240#else
241long rts51x_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
242#endif
243{
244 struct rts51x_chip *chip;
245 struct sd_direct_cmnd cmnd;
246 struct sd_rsp rsp;
247 int retval = 0;
248
249 chip = (struct rts51x_chip *)filp->private_data;
250 if (chip == NULL)
251 return -ENODEV;
252
253 /* lock the device pointers */
254 mutex_lock(&(chip->usb->dev_mutex));
255
256 switch (cmd) {
257 case RTS5139_IOC_SD_DIRECT:
258 retval =
259 copy_from_user((void *)&cmnd, (void *)arg,
260 sizeof(struct sd_direct_cmnd));
261 if (retval) {
262 retval = -ENOMEM;
263 TRACE_GOTO(chip, exit);
264 }
265 retval = rts51x_sd_direct_cmnd(chip, &cmnd);
266 if (retval != STATUS_SUCCESS) {
267 retval = -EIO;
268 TRACE_GOTO(chip, exit);
269 }
270 break;
271
272 case RTS5139_IOC_SD_GET_RSP:
273 retval =
274 copy_from_user((void *)&rsp, (void *)arg,
275 sizeof(struct sd_rsp));
276 if (retval) {
277 retval = -ENOMEM;
278 TRACE_GOTO(chip, exit);
279 }
280 retval = rts51x_sd_get_rsp(chip, &rsp);
281 if (retval != STATUS_SUCCESS) {
282 retval = -EIO;
283 TRACE_GOTO(chip, exit);
284 }
285 break;
286
287 default:
288 break;
289 }
290
291exit:
292 /* unlock the device pointers */
293 mutex_unlock(&chip->usb->dev_mutex);
294
295 return retval;
296}
297
298#endif