1dfe0d3ba20e860d0b9a16c4c6524180b8f93be05Matthew Dharm/* Driver for Rio Karma
2dfe0d3ba20e860d0b9a16c4c6524180b8f93be05Matthew Dharm *
3dfe0d3ba20e860d0b9a16c4c6524180b8f93be05Matthew Dharm *   (c) 2006 Bob Copeland <me@bobcopeland.com>
4dfe0d3ba20e860d0b9a16c4c6524180b8f93be05Matthew Dharm *   (c) 2006 Keith Bennett <keith@mcs.st-and.ac.uk>
5dfe0d3ba20e860d0b9a16c4c6524180b8f93be05Matthew Dharm *
6dfe0d3ba20e860d0b9a16c4c6524180b8f93be05Matthew Dharm * This program is free software; you can redistribute it and/or modify it
7dfe0d3ba20e860d0b9a16c4c6524180b8f93be05Matthew Dharm * under the terms of the GNU General Public License as published by the
8dfe0d3ba20e860d0b9a16c4c6524180b8f93be05Matthew Dharm * Free Software Foundation; either version 2, or (at your option) any
9dfe0d3ba20e860d0b9a16c4c6524180b8f93be05Matthew Dharm * later version.
10dfe0d3ba20e860d0b9a16c4c6524180b8f93be05Matthew Dharm *
11dfe0d3ba20e860d0b9a16c4c6524180b8f93be05Matthew Dharm * This program is distributed in the hope that it will be useful, but
12dfe0d3ba20e860d0b9a16c4c6524180b8f93be05Matthew Dharm * WITHOUT ANY WARRANTY; without even the implied warranty of
13dfe0d3ba20e860d0b9a16c4c6524180b8f93be05Matthew Dharm * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14dfe0d3ba20e860d0b9a16c4c6524180b8f93be05Matthew Dharm * General Public License for more details.
15dfe0d3ba20e860d0b9a16c4c6524180b8f93be05Matthew Dharm *
16dfe0d3ba20e860d0b9a16c4c6524180b8f93be05Matthew Dharm * You should have received a copy of the GNU General Public License along
17dfe0d3ba20e860d0b9a16c4c6524180b8f93be05Matthew Dharm * with this program; if not, write to the Free Software Foundation, Inc.,
18dfe0d3ba20e860d0b9a16c4c6524180b8f93be05Matthew Dharm * 675 Mass Ave, Cambridge, MA 02139, USA.
19dfe0d3ba20e860d0b9a16c4c6524180b8f93be05Matthew Dharm */
20dfe0d3ba20e860d0b9a16c4c6524180b8f93be05Matthew Dharm
21c10337846c93bd914dd3003ffb001adc583b313eAlan Stern#include <linux/module.h>
225a0e3ad6af8660be21ca98a971cd00f331318c05Tejun Heo#include <linux/slab.h>
23c10337846c93bd914dd3003ffb001adc583b313eAlan Stern
24dfe0d3ba20e860d0b9a16c4c6524180b8f93be05Matthew Dharm#include <scsi/scsi.h>
25dfe0d3ba20e860d0b9a16c4c6524180b8f93be05Matthew Dharm#include <scsi/scsi_cmnd.h>
26dfe0d3ba20e860d0b9a16c4c6524180b8f93be05Matthew Dharm#include <scsi/scsi_device.h>
27dfe0d3ba20e860d0b9a16c4c6524180b8f93be05Matthew Dharm
28dfe0d3ba20e860d0b9a16c4c6524180b8f93be05Matthew Dharm#include "usb.h"
29dfe0d3ba20e860d0b9a16c4c6524180b8f93be05Matthew Dharm#include "transport.h"
30dfe0d3ba20e860d0b9a16c4c6524180b8f93be05Matthew Dharm#include "debug.h"
31dfe0d3ba20e860d0b9a16c4c6524180b8f93be05Matthew Dharm
324246b06a33ebdd6593dccaab3aa01eb0c9f8c1c8Maciej GrelaMODULE_DESCRIPTION("Driver for Rio Karma");
334246b06a33ebdd6593dccaab3aa01eb0c9f8c1c8Maciej GrelaMODULE_AUTHOR("Bob Copeland <me@bobcopeland.com>, Keith Bennett <keith@mcs.st-and.ac.uk>");
344246b06a33ebdd6593dccaab3aa01eb0c9f8c1c8Maciej GrelaMODULE_LICENSE("GPL");
354246b06a33ebdd6593dccaab3aa01eb0c9f8c1c8Maciej Grela
36dfe0d3ba20e860d0b9a16c4c6524180b8f93be05Matthew Dharm#define RIO_PREFIX "RIOP\x00"
37dfe0d3ba20e860d0b9a16c4c6524180b8f93be05Matthew Dharm#define RIO_PREFIX_LEN 5
38dfe0d3ba20e860d0b9a16c4c6524180b8f93be05Matthew Dharm#define RIO_SEND_LEN 40
39dfe0d3ba20e860d0b9a16c4c6524180b8f93be05Matthew Dharm#define RIO_RECV_LEN 0x200
40dfe0d3ba20e860d0b9a16c4c6524180b8f93be05Matthew Dharm
41dfe0d3ba20e860d0b9a16c4c6524180b8f93be05Matthew Dharm#define RIO_ENTER_STORAGE 0x1
42dfe0d3ba20e860d0b9a16c4c6524180b8f93be05Matthew Dharm#define RIO_LEAVE_STORAGE 0x2
43dfe0d3ba20e860d0b9a16c4c6524180b8f93be05Matthew Dharm#define RIO_RESET 0xC
44dfe0d3ba20e860d0b9a16c4c6524180b8f93be05Matthew Dharm
45dfe0d3ba20e860d0b9a16c4c6524180b8f93be05Matthew Dharmstruct karma_data {
46dfe0d3ba20e860d0b9a16c4c6524180b8f93be05Matthew Dharm	int in_storage;
47dfe0d3ba20e860d0b9a16c4c6524180b8f93be05Matthew Dharm	char *recv;
48dfe0d3ba20e860d0b9a16c4c6524180b8f93be05Matthew Dharm};
49dfe0d3ba20e860d0b9a16c4c6524180b8f93be05Matthew Dharm
50c10337846c93bd914dd3003ffb001adc583b313eAlan Sternstatic int rio_karma_init(struct us_data *us);
51c10337846c93bd914dd3003ffb001adc583b313eAlan Stern
52c10337846c93bd914dd3003ffb001adc583b313eAlan Stern
53c10337846c93bd914dd3003ffb001adc583b313eAlan Stern/*
54c10337846c93bd914dd3003ffb001adc583b313eAlan Stern * The table of devices
55c10337846c93bd914dd3003ffb001adc583b313eAlan Stern */
56c10337846c93bd914dd3003ffb001adc583b313eAlan Stern#define UNUSUAL_DEV(id_vendor, id_product, bcdDeviceMin, bcdDeviceMax, \
57c10337846c93bd914dd3003ffb001adc583b313eAlan Stern		    vendorName, productName, useProtocol, useTransport, \
58c10337846c93bd914dd3003ffb001adc583b313eAlan Stern		    initFunction, flags) \
59c10337846c93bd914dd3003ffb001adc583b313eAlan Stern{ USB_DEVICE_VER(id_vendor, id_product, bcdDeviceMin, bcdDeviceMax), \
60c10337846c93bd914dd3003ffb001adc583b313eAlan Stern  .driver_info = (flags)|(USB_US_TYPE_STOR<<24) }
61c10337846c93bd914dd3003ffb001adc583b313eAlan Stern
62f35e0d5614b9dbf76ec7b5cbd464914a77c01c88Felipe Balbistatic struct usb_device_id karma_usb_ids[] = {
63c10337846c93bd914dd3003ffb001adc583b313eAlan Stern#	include "unusual_karma.h"
64c10337846c93bd914dd3003ffb001adc583b313eAlan Stern	{ }		/* Terminating entry */
65c10337846c93bd914dd3003ffb001adc583b313eAlan Stern};
66c10337846c93bd914dd3003ffb001adc583b313eAlan SternMODULE_DEVICE_TABLE(usb, karma_usb_ids);
67c10337846c93bd914dd3003ffb001adc583b313eAlan Stern
68c10337846c93bd914dd3003ffb001adc583b313eAlan Stern#undef UNUSUAL_DEV
69c10337846c93bd914dd3003ffb001adc583b313eAlan Stern
70c10337846c93bd914dd3003ffb001adc583b313eAlan Stern/*
71c10337846c93bd914dd3003ffb001adc583b313eAlan Stern * The flags table
72c10337846c93bd914dd3003ffb001adc583b313eAlan Stern */
73c10337846c93bd914dd3003ffb001adc583b313eAlan Stern#define UNUSUAL_DEV(idVendor, idProduct, bcdDeviceMin, bcdDeviceMax, \
74c10337846c93bd914dd3003ffb001adc583b313eAlan Stern		    vendor_name, product_name, use_protocol, use_transport, \
75c10337846c93bd914dd3003ffb001adc583b313eAlan Stern		    init_function, Flags) \
76c10337846c93bd914dd3003ffb001adc583b313eAlan Stern{ \
77c10337846c93bd914dd3003ffb001adc583b313eAlan Stern	.vendorName = vendor_name,	\
78c10337846c93bd914dd3003ffb001adc583b313eAlan Stern	.productName = product_name,	\
79c10337846c93bd914dd3003ffb001adc583b313eAlan Stern	.useProtocol = use_protocol,	\
80c10337846c93bd914dd3003ffb001adc583b313eAlan Stern	.useTransport = use_transport,	\
81c10337846c93bd914dd3003ffb001adc583b313eAlan Stern	.initFunction = init_function,	\
82c10337846c93bd914dd3003ffb001adc583b313eAlan Stern}
83c10337846c93bd914dd3003ffb001adc583b313eAlan Stern
84c10337846c93bd914dd3003ffb001adc583b313eAlan Sternstatic struct us_unusual_dev karma_unusual_dev_list[] = {
85c10337846c93bd914dd3003ffb001adc583b313eAlan Stern#	include "unusual_karma.h"
86c10337846c93bd914dd3003ffb001adc583b313eAlan Stern	{ }		/* Terminating entry */
87c10337846c93bd914dd3003ffb001adc583b313eAlan Stern};
88c10337846c93bd914dd3003ffb001adc583b313eAlan Stern
89c10337846c93bd914dd3003ffb001adc583b313eAlan Stern#undef UNUSUAL_DEV
90c10337846c93bd914dd3003ffb001adc583b313eAlan Stern
91c10337846c93bd914dd3003ffb001adc583b313eAlan Stern
92dfe0d3ba20e860d0b9a16c4c6524180b8f93be05Matthew Dharm/*
93dfe0d3ba20e860d0b9a16c4c6524180b8f93be05Matthew Dharm * Send commands to Rio Karma.
94dfe0d3ba20e860d0b9a16c4c6524180b8f93be05Matthew Dharm *
95dfe0d3ba20e860d0b9a16c4c6524180b8f93be05Matthew Dharm * For each command we send 40 bytes starting 'RIOP\0' followed by
96dfe0d3ba20e860d0b9a16c4c6524180b8f93be05Matthew Dharm * the command number and a sequence number, which the device will ack
97dfe0d3ba20e860d0b9a16c4c6524180b8f93be05Matthew Dharm * with a 512-byte packet with the high four bits set and everything
98dfe0d3ba20e860d0b9a16c4c6524180b8f93be05Matthew Dharm * else null.  Then we send 'RIOP\x80' followed by a zero and the
99dfe0d3ba20e860d0b9a16c4c6524180b8f93be05Matthew Dharm * sequence number, until byte 5 in the response repeats the sequence
100dfe0d3ba20e860d0b9a16c4c6524180b8f93be05Matthew Dharm * number.
101dfe0d3ba20e860d0b9a16c4c6524180b8f93be05Matthew Dharm */
102dfe0d3ba20e860d0b9a16c4c6524180b8f93be05Matthew Dharmstatic int rio_karma_send_command(char cmd, struct us_data *us)
103dfe0d3ba20e860d0b9a16c4c6524180b8f93be05Matthew Dharm{
104dfe0d3ba20e860d0b9a16c4c6524180b8f93be05Matthew Dharm	int result, partial;
105dfe0d3ba20e860d0b9a16c4c6524180b8f93be05Matthew Dharm	unsigned long timeout;
106dfe0d3ba20e860d0b9a16c4c6524180b8f93be05Matthew Dharm	static unsigned char seq = 1;
107dfe0d3ba20e860d0b9a16c4c6524180b8f93be05Matthew Dharm	struct karma_data *data = (struct karma_data *) us->extra;
108dfe0d3ba20e860d0b9a16c4c6524180b8f93be05Matthew Dharm
109dfe0d3ba20e860d0b9a16c4c6524180b8f93be05Matthew Dharm	US_DEBUGP("karma: sending command %04x\n", cmd);
110dfe0d3ba20e860d0b9a16c4c6524180b8f93be05Matthew Dharm	memset(us->iobuf, 0, RIO_SEND_LEN);
111dfe0d3ba20e860d0b9a16c4c6524180b8f93be05Matthew Dharm	memcpy(us->iobuf, RIO_PREFIX, RIO_PREFIX_LEN);
112dfe0d3ba20e860d0b9a16c4c6524180b8f93be05Matthew Dharm	us->iobuf[5] = cmd;
113dfe0d3ba20e860d0b9a16c4c6524180b8f93be05Matthew Dharm	us->iobuf[6] = seq;
114dfe0d3ba20e860d0b9a16c4c6524180b8f93be05Matthew Dharm
115dfe0d3ba20e860d0b9a16c4c6524180b8f93be05Matthew Dharm	timeout = jiffies + msecs_to_jiffies(6000);
116dfe0d3ba20e860d0b9a16c4c6524180b8f93be05Matthew Dharm	for (;;) {
117dfe0d3ba20e860d0b9a16c4c6524180b8f93be05Matthew Dharm		result = usb_stor_bulk_transfer_buf(us, us->send_bulk_pipe,
118dfe0d3ba20e860d0b9a16c4c6524180b8f93be05Matthew Dharm			us->iobuf, RIO_SEND_LEN, &partial);
119dfe0d3ba20e860d0b9a16c4c6524180b8f93be05Matthew Dharm		if (result != USB_STOR_XFER_GOOD)
120dfe0d3ba20e860d0b9a16c4c6524180b8f93be05Matthew Dharm			goto err;
121dfe0d3ba20e860d0b9a16c4c6524180b8f93be05Matthew Dharm
122dfe0d3ba20e860d0b9a16c4c6524180b8f93be05Matthew Dharm		result = usb_stor_bulk_transfer_buf(us, us->recv_bulk_pipe,
123dfe0d3ba20e860d0b9a16c4c6524180b8f93be05Matthew Dharm			data->recv, RIO_RECV_LEN, &partial);
124dfe0d3ba20e860d0b9a16c4c6524180b8f93be05Matthew Dharm		if (result != USB_STOR_XFER_GOOD)
125dfe0d3ba20e860d0b9a16c4c6524180b8f93be05Matthew Dharm			goto err;
126dfe0d3ba20e860d0b9a16c4c6524180b8f93be05Matthew Dharm
127dfe0d3ba20e860d0b9a16c4c6524180b8f93be05Matthew Dharm		if (data->recv[5] == seq)
128dfe0d3ba20e860d0b9a16c4c6524180b8f93be05Matthew Dharm			break;
129dfe0d3ba20e860d0b9a16c4c6524180b8f93be05Matthew Dharm
130dfe0d3ba20e860d0b9a16c4c6524180b8f93be05Matthew Dharm		if (time_after(jiffies, timeout))
131dfe0d3ba20e860d0b9a16c4c6524180b8f93be05Matthew Dharm			goto err;
132dfe0d3ba20e860d0b9a16c4c6524180b8f93be05Matthew Dharm
133dfe0d3ba20e860d0b9a16c4c6524180b8f93be05Matthew Dharm		us->iobuf[4] = 0x80;
134dfe0d3ba20e860d0b9a16c4c6524180b8f93be05Matthew Dharm		us->iobuf[5] = 0;
135dfe0d3ba20e860d0b9a16c4c6524180b8f93be05Matthew Dharm		msleep(50);
136dfe0d3ba20e860d0b9a16c4c6524180b8f93be05Matthew Dharm	}
137dfe0d3ba20e860d0b9a16c4c6524180b8f93be05Matthew Dharm
138dfe0d3ba20e860d0b9a16c4c6524180b8f93be05Matthew Dharm	seq++;
139dfe0d3ba20e860d0b9a16c4c6524180b8f93be05Matthew Dharm	if (seq == 0)
140dfe0d3ba20e860d0b9a16c4c6524180b8f93be05Matthew Dharm		seq = 1;
141dfe0d3ba20e860d0b9a16c4c6524180b8f93be05Matthew Dharm
142dfe0d3ba20e860d0b9a16c4c6524180b8f93be05Matthew Dharm	US_DEBUGP("karma: sent command %04x\n", cmd);
143dfe0d3ba20e860d0b9a16c4c6524180b8f93be05Matthew Dharm	return 0;
144dfe0d3ba20e860d0b9a16c4c6524180b8f93be05Matthew Dharmerr:
145dfe0d3ba20e860d0b9a16c4c6524180b8f93be05Matthew Dharm	US_DEBUGP("karma: command %04x failed\n", cmd);
146dfe0d3ba20e860d0b9a16c4c6524180b8f93be05Matthew Dharm	return USB_STOR_TRANSPORT_FAILED;
147dfe0d3ba20e860d0b9a16c4c6524180b8f93be05Matthew Dharm}
148dfe0d3ba20e860d0b9a16c4c6524180b8f93be05Matthew Dharm
149dfe0d3ba20e860d0b9a16c4c6524180b8f93be05Matthew Dharm/*
150dfe0d3ba20e860d0b9a16c4c6524180b8f93be05Matthew Dharm * Trap START_STOP and READ_10 to leave/re-enter storage mode.
151dfe0d3ba20e860d0b9a16c4c6524180b8f93be05Matthew Dharm * Everything else is propagated to the normal bulk layer.
152dfe0d3ba20e860d0b9a16c4c6524180b8f93be05Matthew Dharm */
153c10337846c93bd914dd3003ffb001adc583b313eAlan Sternstatic int rio_karma_transport(struct scsi_cmnd *srb, struct us_data *us)
154dfe0d3ba20e860d0b9a16c4c6524180b8f93be05Matthew Dharm{
155dfe0d3ba20e860d0b9a16c4c6524180b8f93be05Matthew Dharm	int ret;
156dfe0d3ba20e860d0b9a16c4c6524180b8f93be05Matthew Dharm	struct karma_data *data = (struct karma_data *) us->extra;
157dfe0d3ba20e860d0b9a16c4c6524180b8f93be05Matthew Dharm
158dfe0d3ba20e860d0b9a16c4c6524180b8f93be05Matthew Dharm	if (srb->cmnd[0] == READ_10 && !data->in_storage) {
159dfe0d3ba20e860d0b9a16c4c6524180b8f93be05Matthew Dharm		ret = rio_karma_send_command(RIO_ENTER_STORAGE, us);
160dfe0d3ba20e860d0b9a16c4c6524180b8f93be05Matthew Dharm		if (ret)
161dfe0d3ba20e860d0b9a16c4c6524180b8f93be05Matthew Dharm			return ret;
162dfe0d3ba20e860d0b9a16c4c6524180b8f93be05Matthew Dharm
163dfe0d3ba20e860d0b9a16c4c6524180b8f93be05Matthew Dharm		data->in_storage = 1;
164dfe0d3ba20e860d0b9a16c4c6524180b8f93be05Matthew Dharm		return usb_stor_Bulk_transport(srb, us);
165dfe0d3ba20e860d0b9a16c4c6524180b8f93be05Matthew Dharm	} else if (srb->cmnd[0] == START_STOP) {
166dfe0d3ba20e860d0b9a16c4c6524180b8f93be05Matthew Dharm		ret = rio_karma_send_command(RIO_LEAVE_STORAGE, us);
167dfe0d3ba20e860d0b9a16c4c6524180b8f93be05Matthew Dharm		if (ret)
168dfe0d3ba20e860d0b9a16c4c6524180b8f93be05Matthew Dharm			return ret;
169dfe0d3ba20e860d0b9a16c4c6524180b8f93be05Matthew Dharm
170dfe0d3ba20e860d0b9a16c4c6524180b8f93be05Matthew Dharm		data->in_storage = 0;
171dfe0d3ba20e860d0b9a16c4c6524180b8f93be05Matthew Dharm		return rio_karma_send_command(RIO_RESET, us);
172dfe0d3ba20e860d0b9a16c4c6524180b8f93be05Matthew Dharm	}
173dfe0d3ba20e860d0b9a16c4c6524180b8f93be05Matthew Dharm	return usb_stor_Bulk_transport(srb, us);
174dfe0d3ba20e860d0b9a16c4c6524180b8f93be05Matthew Dharm}
175dfe0d3ba20e860d0b9a16c4c6524180b8f93be05Matthew Dharm
176dfe0d3ba20e860d0b9a16c4c6524180b8f93be05Matthew Dharmstatic void rio_karma_destructor(void *extra)
177dfe0d3ba20e860d0b9a16c4c6524180b8f93be05Matthew Dharm{
178dfe0d3ba20e860d0b9a16c4c6524180b8f93be05Matthew Dharm	struct karma_data *data = (struct karma_data *) extra;
179dfe0d3ba20e860d0b9a16c4c6524180b8f93be05Matthew Dharm	kfree(data->recv);
180dfe0d3ba20e860d0b9a16c4c6524180b8f93be05Matthew Dharm}
181dfe0d3ba20e860d0b9a16c4c6524180b8f93be05Matthew Dharm
182c10337846c93bd914dd3003ffb001adc583b313eAlan Sternstatic int rio_karma_init(struct us_data *us)
183dfe0d3ba20e860d0b9a16c4c6524180b8f93be05Matthew Dharm{
184dfe0d3ba20e860d0b9a16c4c6524180b8f93be05Matthew Dharm	int ret = 0;
185dfe0d3ba20e860d0b9a16c4c6524180b8f93be05Matthew Dharm	struct karma_data *data = kzalloc(sizeof(struct karma_data), GFP_NOIO);
186dfe0d3ba20e860d0b9a16c4c6524180b8f93be05Matthew Dharm	if (!data)
187dfe0d3ba20e860d0b9a16c4c6524180b8f93be05Matthew Dharm		goto out;
188dfe0d3ba20e860d0b9a16c4c6524180b8f93be05Matthew Dharm
189dfe0d3ba20e860d0b9a16c4c6524180b8f93be05Matthew Dharm	data->recv = kmalloc(RIO_RECV_LEN, GFP_NOIO);
190dfe0d3ba20e860d0b9a16c4c6524180b8f93be05Matthew Dharm	if (!data->recv) {
191dfe0d3ba20e860d0b9a16c4c6524180b8f93be05Matthew Dharm		kfree(data);
192dfe0d3ba20e860d0b9a16c4c6524180b8f93be05Matthew Dharm		goto out;
193dfe0d3ba20e860d0b9a16c4c6524180b8f93be05Matthew Dharm	}
194dfe0d3ba20e860d0b9a16c4c6524180b8f93be05Matthew Dharm
195dfe0d3ba20e860d0b9a16c4c6524180b8f93be05Matthew Dharm	us->extra = data;
196dfe0d3ba20e860d0b9a16c4c6524180b8f93be05Matthew Dharm	us->extra_destructor = rio_karma_destructor;
197dfe0d3ba20e860d0b9a16c4c6524180b8f93be05Matthew Dharm	ret = rio_karma_send_command(RIO_ENTER_STORAGE, us);
198dfe0d3ba20e860d0b9a16c4c6524180b8f93be05Matthew Dharm	data->in_storage = (ret == 0);
199dfe0d3ba20e860d0b9a16c4c6524180b8f93be05Matthew Dharmout:
200dfe0d3ba20e860d0b9a16c4c6524180b8f93be05Matthew Dharm	return ret;
201dfe0d3ba20e860d0b9a16c4c6524180b8f93be05Matthew Dharm}
202c10337846c93bd914dd3003ffb001adc583b313eAlan Stern
203c10337846c93bd914dd3003ffb001adc583b313eAlan Sternstatic int karma_probe(struct usb_interface *intf,
204c10337846c93bd914dd3003ffb001adc583b313eAlan Stern			 const struct usb_device_id *id)
205c10337846c93bd914dd3003ffb001adc583b313eAlan Stern{
206c10337846c93bd914dd3003ffb001adc583b313eAlan Stern	struct us_data *us;
207c10337846c93bd914dd3003ffb001adc583b313eAlan Stern	int result;
208c10337846c93bd914dd3003ffb001adc583b313eAlan Stern
209c10337846c93bd914dd3003ffb001adc583b313eAlan Stern	result = usb_stor_probe1(&us, intf, id,
210c10337846c93bd914dd3003ffb001adc583b313eAlan Stern			(id - karma_usb_ids) + karma_unusual_dev_list);
211c10337846c93bd914dd3003ffb001adc583b313eAlan Stern	if (result)
212c10337846c93bd914dd3003ffb001adc583b313eAlan Stern		return result;
213c10337846c93bd914dd3003ffb001adc583b313eAlan Stern
214c10337846c93bd914dd3003ffb001adc583b313eAlan Stern	us->transport_name = "Rio Karma/Bulk";
215c10337846c93bd914dd3003ffb001adc583b313eAlan Stern	us->transport = rio_karma_transport;
216c10337846c93bd914dd3003ffb001adc583b313eAlan Stern	us->transport_reset = usb_stor_Bulk_reset;
217c10337846c93bd914dd3003ffb001adc583b313eAlan Stern
218c10337846c93bd914dd3003ffb001adc583b313eAlan Stern	result = usb_stor_probe2(us);
219c10337846c93bd914dd3003ffb001adc583b313eAlan Stern	return result;
220c10337846c93bd914dd3003ffb001adc583b313eAlan Stern}
221c10337846c93bd914dd3003ffb001adc583b313eAlan Stern
222c10337846c93bd914dd3003ffb001adc583b313eAlan Sternstatic struct usb_driver karma_driver = {
223c10337846c93bd914dd3003ffb001adc583b313eAlan Stern	.name =		"ums-karma",
224c10337846c93bd914dd3003ffb001adc583b313eAlan Stern	.probe =	karma_probe,
225c10337846c93bd914dd3003ffb001adc583b313eAlan Stern	.disconnect =	usb_stor_disconnect,
226c10337846c93bd914dd3003ffb001adc583b313eAlan Stern	.suspend =	usb_stor_suspend,
227c10337846c93bd914dd3003ffb001adc583b313eAlan Stern	.resume =	usb_stor_resume,
228c10337846c93bd914dd3003ffb001adc583b313eAlan Stern	.reset_resume =	usb_stor_reset_resume,
229c10337846c93bd914dd3003ffb001adc583b313eAlan Stern	.pre_reset =	usb_stor_pre_reset,
230c10337846c93bd914dd3003ffb001adc583b313eAlan Stern	.post_reset =	usb_stor_post_reset,
231c10337846c93bd914dd3003ffb001adc583b313eAlan Stern	.id_table =	karma_usb_ids,
232c10337846c93bd914dd3003ffb001adc583b313eAlan Stern	.soft_unbind =	1,
233e73b2db6c9bc5bd9a3c080f286964e594351991aHuajun Li	.no_dynamic_id = 1,
234c10337846c93bd914dd3003ffb001adc583b313eAlan Stern};
235c10337846c93bd914dd3003ffb001adc583b313eAlan Stern
23665db43054065790a75291b0834657445fea2cf56Greg Kroah-Hartmanmodule_usb_driver(karma_driver);
237