0001
0002
0003
0004
0005
0006
0007
0008
0009
0010 #include <linux/usb.h>
0011 #include <linux/slab.h>
0012 #include <linux/module.h>
0013
0014 #include "usb.h"
0015 #include "transport.h"
0016 #include "option_ms.h"
0017 #include "debug.h"
0018
0019 #define ZCD_FORCE_MODEM 0x01
0020 #define ZCD_ALLOW_MS 0x02
0021
0022 static unsigned int option_zero_cd = ZCD_FORCE_MODEM;
0023 module_param(option_zero_cd, uint, S_IRUGO | S_IWUSR);
0024 MODULE_PARM_DESC(option_zero_cd, "ZeroCD mode (1=Force Modem (default),"
0025 " 2=Allow CD-Rom");
0026
0027 #define RESPONSE_LEN 1024
0028
0029 static int option_rezero(struct us_data *us)
0030 {
0031 static const unsigned char rezero_msg[] = {
0032 0x55, 0x53, 0x42, 0x43, 0x78, 0x56, 0x34, 0x12,
0033 0x01, 0x00, 0x00, 0x00, 0x80, 0x00, 0x06, 0x01,
0034 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0035 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
0036 };
0037 char *buffer;
0038 int result;
0039
0040 usb_stor_dbg(us, "Option MS: %s\n", "DEVICE MODE SWITCH");
0041
0042 buffer = kzalloc(RESPONSE_LEN, GFP_KERNEL);
0043 if (buffer == NULL)
0044 return USB_STOR_TRANSPORT_ERROR;
0045
0046 memcpy(buffer, rezero_msg, sizeof(rezero_msg));
0047 result = usb_stor_bulk_transfer_buf(us,
0048 us->send_bulk_pipe,
0049 buffer, sizeof(rezero_msg), NULL);
0050 if (result != USB_STOR_XFER_GOOD) {
0051 result = USB_STOR_XFER_ERROR;
0052 goto out;
0053 }
0054
0055
0056
0057
0058
0059 usb_stor_bulk_transfer_buf(us,
0060 us->recv_bulk_pipe,
0061 buffer, RESPONSE_LEN, NULL);
0062
0063
0064 usb_stor_bulk_transfer_buf(us,
0065 us->recv_bulk_pipe,
0066 buffer, 13, NULL);
0067
0068 result = USB_STOR_XFER_GOOD;
0069
0070 out:
0071 kfree(buffer);
0072 return result;
0073 }
0074
0075 static int option_inquiry(struct us_data *us)
0076 {
0077 static const unsigned char inquiry_msg[] = {
0078 0x55, 0x53, 0x42, 0x43, 0x12, 0x34, 0x56, 0x78,
0079 0x24, 0x00, 0x00, 0x00, 0x80, 0x00, 0x06, 0x12,
0080 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00, 0x00,
0081 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
0082 };
0083 char *buffer;
0084 int result;
0085
0086 usb_stor_dbg(us, "Option MS: %s\n", "device inquiry for vendor name");
0087
0088 buffer = kzalloc(0x24, GFP_KERNEL);
0089 if (buffer == NULL)
0090 return USB_STOR_TRANSPORT_ERROR;
0091
0092 memcpy(buffer, inquiry_msg, sizeof(inquiry_msg));
0093 result = usb_stor_bulk_transfer_buf(us,
0094 us->send_bulk_pipe,
0095 buffer, sizeof(inquiry_msg), NULL);
0096 if (result != USB_STOR_XFER_GOOD) {
0097 result = USB_STOR_XFER_ERROR;
0098 goto out;
0099 }
0100
0101 result = usb_stor_bulk_transfer_buf(us,
0102 us->recv_bulk_pipe,
0103 buffer, 0x24, NULL);
0104 if (result != USB_STOR_XFER_GOOD) {
0105 result = USB_STOR_XFER_ERROR;
0106 goto out;
0107 }
0108
0109 result = memcmp(buffer+8, "Option", 6);
0110
0111 if (result != 0)
0112 result = memcmp(buffer+8, "ZCOPTION", 8);
0113
0114
0115 usb_stor_bulk_transfer_buf(us,
0116 us->recv_bulk_pipe,
0117 buffer, 13, NULL);
0118
0119 out:
0120 kfree(buffer);
0121 return result;
0122 }
0123
0124
0125 int option_ms_init(struct us_data *us)
0126 {
0127 int result;
0128
0129 usb_stor_dbg(us, "Option MS: %s\n", "option_ms_init called");
0130
0131
0132
0133
0134
0135 result = option_inquiry(us);
0136 if (result != 0) {
0137 usb_stor_dbg(us, "Option MS: %s\n",
0138 "vendor is not Option or not determinable, no action taken");
0139 return 0;
0140 } else
0141 usb_stor_dbg(us, "Option MS: %s\n",
0142 "this is a genuine Option device, proceeding");
0143
0144
0145 if (option_zero_cd == ZCD_FORCE_MODEM) {
0146 usb_stor_dbg(us, "Option MS: %s\n", "Forcing Modem Mode");
0147 result = option_rezero(us);
0148 if (result != USB_STOR_XFER_GOOD)
0149 usb_stor_dbg(us, "Option MS: %s\n",
0150 "Failed to switch to modem mode");
0151 return -EIO;
0152 } else if (option_zero_cd == ZCD_ALLOW_MS) {
0153
0154 usb_stor_dbg(us, "Option MS: %s\n",
0155 "Allowing Mass Storage Mode if device requests it");
0156 }
0157
0158 return 0;
0159 }
0160