aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/usb/storage/Kconfig12
-rw-r--r--drivers/usb/storage/Makefile1
-rw-r--r--drivers/usb/storage/initializers.c73
-rw-r--r--drivers/usb/storage/initializers.h1
-rw-r--r--drivers/usb/storage/karma.c155
-rw-r--r--drivers/usb/storage/karma.h7
-rw-r--r--drivers/usb/storage/unusual_devs.h2
-rw-r--r--drivers/usb/storage/usb.c11
-rw-r--r--include/linux/usb_usual.h3
9 files changed, 190 insertions, 75 deletions
diff --git a/drivers/usb/storage/Kconfig b/drivers/usb/storage/Kconfig
index be9eec225743..86e48c42d6af 100644
--- a/drivers/usb/storage/Kconfig
+++ b/drivers/usb/storage/Kconfig
@@ -135,6 +135,18 @@ config USB_STORAGE_ONETOUCH
135 this input in any keybinding software. (e.g. gnome's keyboard short- 135 this input in any keybinding software. (e.g. gnome's keyboard short-
136 cuts) 136 cuts)
137 137
138config USB_STORAGE_KARMA
139 bool "Support for Rio Karma music player"
140 depends on USB_STORAGE
141 help
142 Say Y here to include additional code to support the Rio Karma
143 USB interface.
144
145 This code places the Rio Karma into mass storage mode, enabling
146 it to be mounted as an ordinary filesystem. Performing an eject
147 on the resulting scsi device node returns the Karma to normal
148 operation.
149
138config USB_LIBUSUAL 150config USB_LIBUSUAL
139 bool "The shared table of common (or usual) storage devices" 151 bool "The shared table of common (or usual) storage devices"
140 depends on USB 152 depends on USB
diff --git a/drivers/usb/storage/Makefile b/drivers/usb/storage/Makefile
index 8cbba22508a4..023969b4385b 100644
--- a/drivers/usb/storage/Makefile
+++ b/drivers/usb/storage/Makefile
@@ -20,6 +20,7 @@ usb-storage-obj-$(CONFIG_USB_STORAGE_DATAFAB) += datafab.o
20usb-storage-obj-$(CONFIG_USB_STORAGE_JUMPSHOT) += jumpshot.o 20usb-storage-obj-$(CONFIG_USB_STORAGE_JUMPSHOT) += jumpshot.o
21usb-storage-obj-$(CONFIG_USB_STORAGE_ALAUDA) += alauda.o 21usb-storage-obj-$(CONFIG_USB_STORAGE_ALAUDA) += alauda.o
22usb-storage-obj-$(CONFIG_USB_STORAGE_ONETOUCH) += onetouch.o 22usb-storage-obj-$(CONFIG_USB_STORAGE_ONETOUCH) += onetouch.o
23usb-storage-obj-$(CONFIG_USB_STORAGE_KARMA) += karma.o
23 24
24usb-storage-objs := scsiglue.o protocol.o transport.o usb.o \ 25usb-storage-objs := scsiglue.o protocol.o transport.o usb.o \
25 initializers.o $(usb-storage-obj-y) 26 initializers.o $(usb-storage-obj-y)
diff --git a/drivers/usb/storage/initializers.c b/drivers/usb/storage/initializers.c
index ab173b30076e..5b06f9240d05 100644
--- a/drivers/usb/storage/initializers.c
+++ b/drivers/usb/storage/initializers.c
@@ -45,12 +45,6 @@
45#include "debug.h" 45#include "debug.h"
46#include "transport.h" 46#include "transport.h"
47 47
48#define RIO_MSC 0x08
49#define RIOP_INIT "RIOP\x00\x01\x08"
50#define RIOP_INIT_LEN 7
51#define RIO_SEND_LEN 40
52#define RIO_RECV_LEN 0x200
53
54/* This places the Shuttle/SCM USB<->SCSI bridge devices in multi-target 48/* This places the Shuttle/SCM USB<->SCSI bridge devices in multi-target
55 * mode */ 49 * mode */
56int usb_stor_euscsi_init(struct us_data *us) 50int usb_stor_euscsi_init(struct us_data *us)
@@ -97,70 +91,3 @@ int usb_stor_ucr61s2b_init(struct us_data *us)
97 91
98 return (res ? -1 : 0); 92 return (res ? -1 : 0);
99} 93}
100
101/* Place the Rio Karma into mass storage mode.
102 *
103 * The initialization begins by sending 40 bytes starting
104 * RIOP\x00\x01\x08\x00, which the device will ack with a 512-byte
105 * packet with the high four bits set and everything else null.
106 *
107 * Next, we send RIOP\x80\x00\x08\x00. Each time, a 512 byte response
108 * must be read, but we must loop until byte 5 in the response is 0x08,
109 * indicating success. */
110int rio_karma_init(struct us_data *us)
111{
112 int result, partial;
113 char *recv;
114 unsigned long timeout;
115
116 // us->iobuf is big enough to hold cmd but not receive
117 if (!(recv = kmalloc(RIO_RECV_LEN, GFP_KERNEL)))
118 goto die_nomem;
119
120 US_DEBUGP("Initializing Karma...\n");
121
122 memset(us->iobuf, 0, RIO_SEND_LEN);
123 memcpy(us->iobuf, RIOP_INIT, RIOP_INIT_LEN);
124
125 result = usb_stor_bulk_transfer_buf(us, us->send_bulk_pipe,
126 us->iobuf, RIO_SEND_LEN, &partial);
127 if (result != USB_STOR_XFER_GOOD)
128 goto die;
129
130 result = usb_stor_bulk_transfer_buf(us, us->recv_bulk_pipe,
131 recv, RIO_RECV_LEN, &partial);
132 if (result != USB_STOR_XFER_GOOD)
133 goto die;
134
135 us->iobuf[4] = 0x80;
136 us->iobuf[5] = 0;
137 timeout = jiffies + msecs_to_jiffies(3000);
138 for (;;) {
139 US_DEBUGP("Sending init command\n");
140 result = usb_stor_bulk_transfer_buf(us, us->send_bulk_pipe,
141 us->iobuf, RIO_SEND_LEN, &partial);
142 if (result != USB_STOR_XFER_GOOD)
143 goto die;
144
145 result = usb_stor_bulk_transfer_buf(us, us->recv_bulk_pipe,
146 recv, RIO_RECV_LEN, &partial);
147 if (result != USB_STOR_XFER_GOOD)
148 goto die;
149
150 if (recv[5] == RIO_MSC)
151 break;
152 if (time_after(jiffies, timeout))
153 goto die;
154 msleep(10);
155 }
156 US_DEBUGP("Karma initialized.\n");
157 kfree(recv);
158 return 0;
159
160die:
161 kfree(recv);
162die_nomem:
163 US_DEBUGP("Could not initialize karma.\n");
164 return USB_STOR_TRANSPORT_FAILED;
165}
166
diff --git a/drivers/usb/storage/initializers.h b/drivers/usb/storage/initializers.h
index 927f7781080f..e2967a4d48a2 100644
--- a/drivers/usb/storage/initializers.h
+++ b/drivers/usb/storage/initializers.h
@@ -47,4 +47,3 @@ int usb_stor_euscsi_init(struct us_data *us);
47/* This function is required to activate all four slots on the UCR-61S2B 47/* This function is required to activate all four slots on the UCR-61S2B
48 * flash reader */ 48 * flash reader */
49int usb_stor_ucr61s2b_init(struct us_data *us); 49int usb_stor_ucr61s2b_init(struct us_data *us);
50int rio_karma_init(struct us_data *us);
diff --git a/drivers/usb/storage/karma.c b/drivers/usb/storage/karma.c
new file mode 100644
index 000000000000..0d79ae5683f7
--- /dev/null
+++ b/drivers/usb/storage/karma.c
@@ -0,0 +1,155 @@
1/* Driver for Rio Karma
2 *
3 * (c) 2006 Bob Copeland <me@bobcopeland.com>
4 * (c) 2006 Keith Bennett <keith@mcs.st-and.ac.uk>
5 *
6 * This program is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License as published by the
8 * Free Software Foundation; either version 2, or (at your option) any
9 * later version.
10 *
11 * This program is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License along
17 * with this program; if not, write to the Free Software Foundation, Inc.,
18 * 675 Mass Ave, Cambridge, MA 02139, USA.
19 */
20
21#include <scsi/scsi.h>
22#include <scsi/scsi_cmnd.h>
23#include <scsi/scsi_device.h>
24
25#include "usb.h"
26#include "transport.h"
27#include "debug.h"
28#include "karma.h"
29
30#define RIO_PREFIX "RIOP\x00"
31#define RIO_PREFIX_LEN 5
32#define RIO_SEND_LEN 40
33#define RIO_RECV_LEN 0x200
34
35#define RIO_ENTER_STORAGE 0x1
36#define RIO_LEAVE_STORAGE 0x2
37#define RIO_RESET 0xC
38
39extern int usb_stor_Bulk_transport(struct scsi_cmnd *, struct us_data *);
40
41struct karma_data {
42 int in_storage;
43 char *recv;
44};
45
46/*
47 * Send commands to Rio Karma.
48 *
49 * For each command we send 40 bytes starting 'RIOP\0' followed by
50 * the command number and a sequence number, which the device will ack
51 * with a 512-byte packet with the high four bits set and everything
52 * else null. Then we send 'RIOP\x80' followed by a zero and the
53 * sequence number, until byte 5 in the response repeats the sequence
54 * number.
55 */
56static int rio_karma_send_command(char cmd, struct us_data *us)
57{
58 int result, partial;
59 unsigned long timeout;
60 static unsigned char seq = 1;
61 struct karma_data *data = (struct karma_data *) us->extra;
62
63 US_DEBUGP("karma: sending command %04x\n", cmd);
64 memset(us->iobuf, 0, RIO_SEND_LEN);
65 memcpy(us->iobuf, RIO_PREFIX, RIO_PREFIX_LEN);
66 us->iobuf[5] = cmd;
67 us->iobuf[6] = seq;
68
69 timeout = jiffies + msecs_to_jiffies(6000);
70 for (;;) {
71 result = usb_stor_bulk_transfer_buf(us, us->send_bulk_pipe,
72 us->iobuf, RIO_SEND_LEN, &partial);
73 if (result != USB_STOR_XFER_GOOD)
74 goto err;
75
76 result = usb_stor_bulk_transfer_buf(us, us->recv_bulk_pipe,
77 data->recv, RIO_RECV_LEN, &partial);
78 if (result != USB_STOR_XFER_GOOD)
79 goto err;
80
81 if (data->recv[5] == seq)
82 break;
83
84 if (time_after(jiffies, timeout))
85 goto err;
86
87 us->iobuf[4] = 0x80;
88 us->iobuf[5] = 0;
89 msleep(50);
90 }
91
92 seq++;
93 if (seq == 0)
94 seq = 1;
95
96 US_DEBUGP("karma: sent command %04x\n", cmd);
97 return 0;
98err:
99 US_DEBUGP("karma: command %04x failed\n", cmd);
100 return USB_STOR_TRANSPORT_FAILED;
101}
102
103/*
104 * Trap START_STOP and READ_10 to leave/re-enter storage mode.
105 * Everything else is propagated to the normal bulk layer.
106 */
107int rio_karma_transport(struct scsi_cmnd *srb, struct us_data *us)
108{
109 int ret;
110 struct karma_data *data = (struct karma_data *) us->extra;
111
112 if (srb->cmnd[0] == READ_10 && !data->in_storage) {
113 ret = rio_karma_send_command(RIO_ENTER_STORAGE, us);
114 if (ret)
115 return ret;
116
117 data->in_storage = 1;
118 return usb_stor_Bulk_transport(srb, us);
119 } else if (srb->cmnd[0] == START_STOP) {
120 ret = rio_karma_send_command(RIO_LEAVE_STORAGE, us);
121 if (ret)
122 return ret;
123
124 data->in_storage = 0;
125 return rio_karma_send_command(RIO_RESET, us);
126 }
127 return usb_stor_Bulk_transport(srb, us);
128}
129
130static void rio_karma_destructor(void *extra)
131{
132 struct karma_data *data = (struct karma_data *) extra;
133 kfree(data->recv);
134}
135
136int rio_karma_init(struct us_data *us)
137{
138 int ret = 0;
139 struct karma_data *data = kzalloc(sizeof(struct karma_data), GFP_NOIO);
140 if (!data)
141 goto out;
142
143 data->recv = kmalloc(RIO_RECV_LEN, GFP_NOIO);
144 if (!data->recv) {
145 kfree(data);
146 goto out;
147 }
148
149 us->extra = data;
150 us->extra_destructor = rio_karma_destructor;
151 ret = rio_karma_send_command(RIO_ENTER_STORAGE, us);
152 data->in_storage = (ret == 0);
153out:
154 return ret;
155}
diff --git a/drivers/usb/storage/karma.h b/drivers/usb/storage/karma.h
new file mode 100644
index 000000000000..8a60972af8c5
--- /dev/null
+++ b/drivers/usb/storage/karma.h
@@ -0,0 +1,7 @@
1#ifndef _KARMA_USB_H
2#define _KARMA_USB_H
3
4extern int rio_karma_init(struct us_data *us);
5extern int rio_karma_transport(struct scsi_cmnd *srb, struct us_data *us);
6
7#endif
diff --git a/drivers/usb/storage/unusual_devs.h b/drivers/usb/storage/unusual_devs.h
index fa49357289c4..1f11c9d44eaa 100644
--- a/drivers/usb/storage/unusual_devs.h
+++ b/drivers/usb/storage/unusual_devs.h
@@ -221,7 +221,7 @@ UNUSUAL_DEV( 0x0457, 0x0151, 0x0100, 0x0100,
221UNUSUAL_DEV( 0x045a, 0x5210, 0x0101, 0x0101, 221UNUSUAL_DEV( 0x045a, 0x5210, 0x0101, 0x0101,
222 "Rio", 222 "Rio",
223 "Rio Karma", 223 "Rio Karma",
224 US_SC_SCSI, US_PR_BULK, rio_karma_init, 0), 224 US_SC_SCSI, US_PR_KARMA, rio_karma_init, 0),
225 225
226/* Patch submitted by Philipp Friedrich <philipp@void.at> */ 226/* Patch submitted by Philipp Friedrich <philipp@void.at> */
227UNUSUAL_DEV( 0x0482, 0x0100, 0x0100, 0x0100, 227UNUSUAL_DEV( 0x0482, 0x0100, 0x0100, 0x0100,
diff --git a/drivers/usb/storage/usb.c b/drivers/usb/storage/usb.c
index 8d7bdcb5924d..b8d6031b0975 100644
--- a/drivers/usb/storage/usb.c
+++ b/drivers/usb/storage/usb.c
@@ -98,6 +98,9 @@
98#ifdef CONFIG_USB_STORAGE_ALAUDA 98#ifdef CONFIG_USB_STORAGE_ALAUDA
99#include "alauda.h" 99#include "alauda.h"
100#endif 100#endif
101#ifdef CONFIG_USB_STORAGE_KARMA
102#include "karma.h"
103#endif
101 104
102/* Some informational data */ 105/* Some informational data */
103MODULE_AUTHOR("Matthew Dharm <mdharm-usb@one-eyed-alien.net>"); 106MODULE_AUTHOR("Matthew Dharm <mdharm-usb@one-eyed-alien.net>");
@@ -646,6 +649,14 @@ static int get_transport(struct us_data *us)
646 break; 649 break;
647#endif 650#endif
648 651
652#ifdef CONFIG_USB_STORAGE_KARMA
653 case US_PR_KARMA:
654 us->transport_name = "Rio Karma/Bulk";
655 us->transport = rio_karma_transport;
656 us->transport_reset = usb_stor_Bulk_reset;
657 break;
658#endif
659
649 default: 660 default:
650 return -EIO; 661 return -EIO;
651 } 662 }
diff --git a/include/linux/usb_usual.h b/include/linux/usb_usual.h
index e7fc5fed5b98..2ae76fe52ff7 100644
--- a/include/linux/usb_usual.h
+++ b/include/linux/usb_usual.h
@@ -108,6 +108,9 @@ enum { US_DO_ALL_FLAGS };
108#ifdef CONFIG_USB_STORAGE_ALAUDA 108#ifdef CONFIG_USB_STORAGE_ALAUDA
109#define US_PR_ALAUDA 0xf4 /* Alauda chipsets */ 109#define US_PR_ALAUDA 0xf4 /* Alauda chipsets */
110#endif 110#endif
111#ifdef CONFIG_USB_STORAGE_KARMA
112#define US_PR_KARMA 0xf5 /* Rio Karma */
113#endif
111 114
112#define US_PR_DEVICE 0xff /* Use device's value */ 115#define US_PR_DEVICE 0xff /* Use device's value */
113 116