Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit abb02fdf authored by Matthew Dharm's avatar Matthew Dharm Committed by Greg Kroah-Hartman
Browse files

[PATCH] USB: usb-storage: Add support for Rio Karma



This patch from Bob Copeland adds support for the Rio Karma portable
digital audio player to the usb-storage driver.  The only thing needed to
support this device is a one-time (per plugin) init command which is sent
to the device.

Signed-off-by: default avatarBob Copeland <me@bobcopeland.com>
Signed-off-by: default avatarMatthew Dharm <mdharm-usb@one-eyed-alien.net>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@suse.de>
parent 8e2ce4f9
Loading
Loading
Loading
Loading
+73 −0
Original line number Diff line number Diff line
@@ -45,6 +45,12 @@
#include "debug.h"
#include "transport.h"

#define RIO_MSC 0x08
#define RIOP_INIT "RIOP\x00\x01\x08"
#define RIOP_INIT_LEN 7
#define RIO_SEND_LEN 40
#define RIO_RECV_LEN 0x200

/* This places the Shuttle/SCM USB<->SCSI bridge devices in multi-target
 * mode */
int usb_stor_euscsi_init(struct us_data *us)
@@ -91,3 +97,70 @@ int usb_stor_ucr61s2b_init(struct us_data *us)

	return (res ? -1 : 0);
}

/* Place the Rio Karma into mass storage mode.
 *
 * The initialization begins by sending 40 bytes starting
 * RIOP\x00\x01\x08\x00, which the device will ack with a 512-byte
 * packet with the high four bits set and everything else null.
 *
 * Next, we send RIOP\x80\x00\x08\x00.  Each time, a 512 byte response
 * must be read, but we must loop until byte 5 in the response is 0x08,
 * indicating success.  */
int rio_karma_init(struct us_data *us)
{
	int result, partial;
	char *recv;
	unsigned long timeout;

	// us->iobuf is big enough to hold cmd but not receive
	if (!(recv = kmalloc(RIO_RECV_LEN, GFP_KERNEL)))
		goto die_nomem;

	US_DEBUGP("Initializing Karma...\n");

	memset(us->iobuf, 0, RIO_SEND_LEN);
	memcpy(us->iobuf, RIOP_INIT, RIOP_INIT_LEN);

	result = usb_stor_bulk_transfer_buf(us, us->send_bulk_pipe,
		us->iobuf, RIO_SEND_LEN, &partial);
	if (result != USB_STOR_XFER_GOOD)
		goto die;

	result = usb_stor_bulk_transfer_buf(us, us->recv_bulk_pipe,
		recv, RIO_RECV_LEN, &partial);
	if (result != USB_STOR_XFER_GOOD)
		goto die;

	us->iobuf[4] = 0x80;
	us->iobuf[5] = 0;
	timeout = jiffies + msecs_to_jiffies(3000);
	for (;;) {
		US_DEBUGP("Sending init command\n");
		result = usb_stor_bulk_transfer_buf(us, us->send_bulk_pipe,
			us->iobuf, RIO_SEND_LEN, &partial);
		if (result != USB_STOR_XFER_GOOD)
			goto die;

		result = usb_stor_bulk_transfer_buf(us, us->recv_bulk_pipe,
			recv, RIO_RECV_LEN, &partial);
		if (result != USB_STOR_XFER_GOOD)
			goto die;

		if (recv[5] == RIO_MSC)
			break;
		if (time_after(jiffies, timeout))
			goto die;
		msleep(10);
	}
	US_DEBUGP("Karma initialized.\n");
	kfree(recv);
	return 0;

die:
	kfree(recv);
die_nomem:
	US_DEBUGP("Could not initialize karma.\n");
	return USB_STOR_TRANSPORT_FAILED;
}
+1 −0
Original line number Diff line number Diff line
@@ -48,3 +48,4 @@ int usb_stor_euscsi_init(struct us_data *us);
/* This function is required to activate all four slots on the UCR-61S2B
 * flash reader */
int usb_stor_ucr61s2b_init(struct us_data *us);
int rio_karma_init(struct us_data *us);
+5 −0
Original line number Diff line number Diff line
@@ -145,6 +145,11 @@ UNUSUAL_DEV( 0x0451, 0x5416, 0x0100, 0x0100,
		US_SC_DEVICE, US_PR_BULK, NULL,
		US_FL_NEED_OVERRIDE ),

UNUSUAL_DEV(  0x045a, 0x5210, 0x0101, 0x0101,
		"Rio",
		"Rio Karma",
		US_SC_SCSI, US_PR_BULK, rio_karma_init, 0),

/* Patch submitted by Philipp Friedrich <philipp@void.at> */
UNUSUAL_DEV(  0x0482, 0x0100, 0x0100, 0x0100,
		"Kyocera",