• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 #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 
rts51x_sd_direct_cmnd(struct rts51x_chip * chip,struct sd_direct_cmnd * cmnd)46 static 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 
rts51x_sd_get_rsp(struct rts51x_chip * chip,struct sd_rsp * rsp)141 static 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 
rts51x_open(struct inode * inode,struct file * filp)170 int 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 
206 exit:
207 	return retval;
208 }
209 
rts51x_release(struct inode * inode,struct file * filp)210 int 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 
rts51x_read(struct file * filp,char __user * buf,size_t count,loff_t * f_pos)225 ssize_t rts51x_read(struct file *filp, char __user *buf, size_t count,
226 		    loff_t *f_pos)
227 {
228 	return 0;
229 }
230 
rts51x_write(struct file * filp,const char __user * buf,size_t count,loff_t * f_pos)231 ssize_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) */
238 int rts51x_ioctl(struct inode *inode, struct file *filp, unsigned int cmd,
239 		 unsigned long arg)
240 #else
rts51x_ioctl(struct file * filp,unsigned int cmd,unsigned long arg)241 long 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 
291 exit:
292 	/* unlock the device pointers */
293 	mutex_unlock(&chip->usb->dev_mutex);
294 
295 	return retval;
296 }
297 
298 #endif
299