1 //<MStar Software>
2 //******************************************************************************
3 // MStar Software
4 // Copyright (c) 2010 - 2012 MStar Semiconductor, Inc. All rights reserved.
5 // All software, firmware and related documentation herein ("MStar Software") are
6 // intellectual property of MStar Semiconductor, Inc. ("MStar") and protected by
7 // law, including, but not limited to, copyright law and international treaties.
8 // Any use, modification, reproduction, retransmission, or republication of all
9 // or part of MStar Software is expressly prohibited, unless prior written
10 // permission has been granted by MStar.
11 //
12 // By accessing, browsing and/or using MStar Software, you acknowledge that you
13 // have read, understood, and agree, to be bound by below terms ("Terms") and to
14 // comply with all applicable laws and regulations:
15 //
16 // 1. MStar shall retain any and all right, ownership and interest to MStar
17 // Software and any modification/derivatives thereof.
18 // No right, ownership, or interest to MStar Software and any
19 // modification/derivatives thereof is transferred to you under Terms.
20 //
21 // 2. You understand that MStar Software might include, incorporate or be
22 // supplied together with third party`s software and the use of MStar
23 // Software may require additional licenses from third parties.
24 // Therefore, you hereby agree it is your sole responsibility to separately
25 // obtain any and all third party right and license necessary for your use of
26 // such third party`s software.
27 //
28 // 3. MStar Software and any modification/derivatives thereof shall be deemed as
29 // MStar`s confidential information and you agree to keep MStar`s
30 // confidential information in strictest confidence and not disclose to any
31 // third party.
32 //
33 // 4. MStar Software is provided on an "AS IS" basis without warranties of any
34 // kind. Any warranties are hereby expressly disclaimed by MStar, including
35 // without limitation, any warranties of merchantability, non-infringement of
36 // intellectual property rights, fitness for a particular purpose, error free
37 // and in conformity with any international standard. You agree to waive any
38 // claim against MStar for any loss, damage, cost or expense that you may
39 // incur related to your use of MStar Software.
40 // In no event shall MStar be liable for any direct, indirect, incidental or
41 // consequential damages, including without limitation, lost of profit or
42 // revenues, lost or damage of data, and unauthorized system use.
43 // You agree that this Section 4 shall still apply without being affected
44 // even if MStar Software has been modified by MStar in accordance with your
45 // request or instruction for your use, except otherwise agreed by both
46 // parties in writing.
47 //
48 // 5. If requested, MStar may from time to time provide technical supports or
49 // services in relation with MStar Software to you for your use of
50 // MStar Software in conjunction with your or your customer`s product
51 // ("Services").
52 // You understand and agree that, except otherwise agreed by both parties in
53 // writing, Services are provided on an "AS IS" basis and the warranty
54 // disclaimer set forth in Section 4 above shall apply.
55 //
56 // 6. Nothing contained herein shall be construed as by implication, estoppels
57 // or otherwise:
58 // (a) conferring any license or right to use MStar name, trademark, service
59 // mark, symbol or any other identification;
60 // (b) obligating MStar or any of its affiliates to furnish any person,
61 // including without limitation, you and your customers, any assistance
62 // of any kind whatsoever, or any information; or
63 // (c) conferring any license or right under any intellectual property right.
64 //
65 // 7. These terms shall be governed by and construed in accordance with the laws
66 // of Taiwan, R.O.C., excluding its conflict of law rules.
67 // Any and all dispute arising out hereof or related hereto shall be finally
68 // settled by arbitration referred to the Chinese Arbitration Association,
69 // Taipei in accordance with the ROC Arbitration Law and the Arbitration
70 // Rules of the Association by three (3) arbitrators appointed in accordance
71 // with the said Rules.
72 // The place of arbitration shall be in Taipei, Taiwan and the language shall
73 // be English.
74 // The arbitration award shall be final and binding to both parties.
75 //
76 //******************************************************************************
77 //<MStar Software>
78
79 //=============================================================================
80 //================include file======================//
81 //#include <MsCommon.h> // NUSED
82 #include "include/drvConfig.h"
83 //#include "include/drvErrno.h" // NUSED
84 //#include "include/drvUSBHost.h" // NUSED
85 #include "drvBulktran.h"
86 #include "include/drvBitops.h"
87 //#include "include/drvCPE_AMBA.h" // NUSED
88 //#include "drvUsbHostConfig.h" // NUSED
89 #include "drvUsbd.h"
90 //==================================================//
91
92 //==================Definition======================//
93 static int ms_usb_msc_probe(struct usb_interface *iface, const struct usb_device_id *id);
94 static void ms_usb_msc_disconnect(struct usb_interface *iface);
95 extern void RemoveUSBDiskPort(U8 uPort, U8 uLunNum);
96
97 #define GET_INTERFACE_INFO(cl,sc,pr) \
98 USB_DEVICE_ID_MATCH_INT_INFO,0,0,0,0,0,0,0, (cl), (sc), (pr),0
99 //==================================================//
100
101 static struct usb_device_id MSC_usb_ids [] =
102 {
103 {GET_INTERFACE_INFO (USB_CLASS_STORAGE, MS_RBC_SC, MS_CB_PR) },
104 {GET_INTERFACE_INFO (USB_CLASS_STORAGE, MS_ATAPI_SC,MS_CB_PR) },
105 {GET_INTERFACE_INFO (USB_CLASS_STORAGE, MS_QIC_SC, MS_CB_PR) },
106 {GET_INTERFACE_INFO (USB_CLASS_STORAGE, MS_UFI_SC, MS_CB_PR) },
107 {GET_INTERFACE_INFO (USB_CLASS_STORAGE, MS_SFF_SC,MS_CB_PR) },
108 {GET_INTERFACE_INFO (USB_CLASS_STORAGE, MS_SCSI_SC,MS_CB_PR) },
109 {GET_INTERFACE_INFO (USB_CLASS_STORAGE, MS_RBC_SC, MS_CBI_PR) },
110 {GET_INTERFACE_INFO (USB_CLASS_STORAGE, MS_ATAPI_SC, MS_CBI_PR) },
111 {GET_INTERFACE_INFO (USB_CLASS_STORAGE, MS_QIC_SC, MS_CBI_PR) },
112 {GET_INTERFACE_INFO (USB_CLASS_STORAGE, MS_UFI_SC, MS_CBI_PR) },
113 {GET_INTERFACE_INFO (USB_CLASS_STORAGE, MS_SFF_SC, MS_CBI_PR) },
114 {GET_INTERFACE_INFO (USB_CLASS_STORAGE, MS_SCSI_SC, MS_CBI_PR) },
115 {GET_INTERFACE_INFO (USB_CLASS_STORAGE, MS_RBC_SC, MS_BULK_PR) },
116 {GET_INTERFACE_INFO (USB_CLASS_STORAGE, MS_ATAPI_SC, MS_BULK_PR) },
117 {GET_INTERFACE_INFO (USB_CLASS_STORAGE, MS_QIC_SC, MS_BULK_PR) },
118 {GET_INTERFACE_INFO (USB_CLASS_STORAGE, MS_UFI_SC, MS_BULK_PR) },
119 {GET_INTERFACE_INFO (USB_CLASS_STORAGE, MS_SFF_SC, MS_BULK_PR) },
120 {GET_INTERFACE_INFO (USB_CLASS_STORAGE, MS_SCSI_SC, MS_BULK_PR) },
121 {GET_INTERFACE_INFO (USB_CLASS_STORAGE, 0xFF, MS_CB_PR) },
122 {0,0,0,0,0,0,0,0,0,0,0,0}
123 };
124
125 static struct stUnusual_dev MS_USB_unusual_dev_list[] =
126 {
127 { 0,0, MS_RBC_SC, MS_CB_PR,0,0 },
128 { 0,0, MS_ATAPI_SC, MS_CB_PR,0,0 },
129 { 0,0, MS_QIC_SC, MS_CB_PR,0,0 },
130 { 0,0, MS_UFI_SC, MS_CB_PR,0,0 },
131 { 0,0, MS_SFF_SC, MS_CB_PR,0,0 },
132 { 0,0, MS_SCSI_SC, MS_CB_PR,0,0 },
133 { 0,0, MS_RBC_SC, MS_CBI_PR,0,0 },
134 { 0,0, MS_ATAPI_SC, MS_CBI_PR,0,0 },
135 { 0,0, MS_QIC_SC, MS_CBI_PR,0,0 },
136 { 0,0, MS_UFI_SC, MS_CBI_PR,0,0 },
137 { 0,0, MS_SFF_SC, MS_CBI_PR,0,0 },
138 { 0,0, MS_SCSI_SC, MS_CBI_PR,0,0 },
139 { 0,0, MS_RBC_SC, MS_BULK_PR,0,0 },
140 { 0,0, MS_ATAPI_SC, MS_BULK_PR,0,0 },
141 { 0,0, MS_QIC_SC, MS_BULK_PR,0,0 },
142 { 0,0, MS_UFI_SC, MS_BULK_PR,0,0 },
143 { 0,0, MS_SFF_SC, MS_BULK_PR,0,0 },
144 { 0,0, MS_SCSI_SC, MS_BULK_PR,0,0 },
145 { 0,0, 0xFF, MS_CB_PR,0,0 },
146 { 0,0,0,0,0,0 }
147 };
148
149 struct usb_driver usb_storage_driver =
150 {
151 "usb-storage",
152 ms_usb_msc_probe,
153 ms_usb_msc_disconnect,
154 MSC_usb_ids
155 };
156
ms_usb_inquiry_data(struct ms_usdata * ms_us)157 static void ms_usb_inquiry_data(struct ms_usdata *ms_us)
158 {
159 U32 data_len=36;
160 int len,len1,len2;
161 unsigned char data_ptr[36] = {0x00, 0x80, 0x02, 0x02, 0x1F, 0x00, 0x00, 0x00};
162
163 if (ms_test_bit(MS_IDX_DISCONNECTING, &ms_us->flags))
164 {
165 ms_usbhost_msg("No command allowed during disconnection\n");
166 ms_us->srb.result = DID_BAD_TARGET << 16;
167 }
168 else if (ms_us->srb.sc_data_direction == SCSI_DATA_UNKNOWN)
169 {
170 ms_usbhost_msg("UNKNOWN data direction\n");
171 ms_us->srb.result = DID_ERROR << 16;
172 }
173 else if ((ms_us->srb.cmnd[0] == INQUIRY) && (ms_us->flags & MS_FIX_INQUIRY))
174 {
175 ms_usbhost_msg("Faking INQUIRY command\n");
176 if(ms_us->srb.req_buf_len > data_len)
177 len=data_len;
178 else
179 len=ms_us->srb.req_buf_len;
180
181 if(data_len >= 36)
182 {
183 if(data_ptr[0]&0x20)
184 memset(data_ptr+8,0,28);
185 else
186 {
187 if(strlen(ms_us->unusual_dev->vendorName) > 8)
188 len1 = 8;
189 else
190 len1 = strlen(ms_us->unusual_dev->vendorName);
191 memcpy(data_ptr+8, ms_us->unusual_dev->vendorName,len1);
192
193 if(strlen(ms_us->unusual_dev->productName) > 16)
194 len2 = 16;
195 else
196 len2 = strlen(ms_us->unusual_dev->productName);
197 memcpy(data_ptr+16, ms_us->unusual_dev->productName,len2);
198
199 data_ptr[32] = 0x30 + ((ms_us->pusb_dev->descriptor.bcdDevice>>12) & 0x0F);
200 data_ptr[33] = 0x30 + ((ms_us->pusb_dev->descriptor.bcdDevice>>8) & 0x0F);
201 data_ptr[34] = 0x30 + ((ms_us->pusb_dev->descriptor.bcdDevice>>4) & 0x0F);
202 data_ptr[35] = 0x30 + ((ms_us->pusb_dev->descriptor.bcdDevice) & 0x0F);
203 }
204
205 memset(ms_us->srb.req_buf, 0, ms_us->srb.req_buf_len);
206 memcpy(ms_us->srb.req_buf, data_ptr, len);
207 }
208
209 ms_us->srb.result = MS_STAT_GOOD;
210 }
211 else
212 ms_us->proto_handler(&ms_us->srb, ms_us);
213 }
214
ms_usb_msc_control_thread(void * __us)215 int ms_usb_msc_control_thread(void * __us)
216 {
217 struct ms_usdata *ms_us = (struct ms_usdata *)__us;
218
219 ms_usbhost_debug("*** thread awakened.\n");
220 //if (ms_us->usb_state == ABORTING_STATE)
221 //{
222 // ms_us->srb.result = DID_ABORT << 16;
223 // goto Stop_transfer;
224 //}
225 //ms_us->usb_state = RUNNING_STATE;
226 //osapi_down(&(ms_us->dev_semaphore));
227 osapi_mutex_lock(ms_us->dev_mutex);
228 ms_usb_inquiry_data(ms_us);
229 //osapi_up(&(ms_us->dev_semaphore)); //unlock the device pointers
230 osapi_mutex_unlock(ms_us->dev_mutex);
231
232 /* lock access to the state */
233 /* indicate that the command is done */
234 if (ms_us->srb.result != DID_ABORT << 16)
235 {
236 ms_usbhost_debug("SCSI cmd done, result=0x%x\n", ms_us->srb.result);
237 if(ms_us->srb.scsi_done != NULL)
238 ms_us->srb.scsi_done(&ms_us->srb);
239 }
240 else
241 {
242 //Stop_transfer:
243 ms_usbhost_msg("SCSI command aborted\n");
244 }
245 //if (ms_us->usb_state == ABORTING_STATE)
246 // complete(&(ms_us->notify));
247 //ms_us->usb_state = IDLE_STATE;
248 //complete(&(ms_us->notify));
249
250 return 0;
251 }
252
ms_usb_associate_dev(struct ms_usdata * ms_us,struct usb_interface * ms_intf)253 static int ms_usb_associate_dev(struct ms_usdata *ms_us, struct usb_interface *ms_intf)
254 {
255 ms_us->pusb_dev = interface_to_usbdev(ms_intf);
256 ms_us->pusb_intf = ms_intf;
257 ms_us->ifnum = ms_intf->altsetting->desc.bInterfaceNumber;
258
259 ms_usb_set_intfdata(ms_intf, ms_us);
260 ms_usb_get_dev(ms_us->pusb_dev);
261 ms_us->cr = (struct usb_ctrlrequest*) ms_usb_buffer_alloc(ms_us->pusb_dev, sizeof(*ms_us->cr), GFP_KERNEL, &ms_us->cr_dma);
262 ms_us->iobuf = (unsigned char*) ms_usb_buffer_alloc(ms_us->pusb_dev, MS_IOBUF_SIZE, GFP_KERNEL, &ms_us->iobuf_dma);
263 if((!ms_us->cr) || (!ms_us->iobuf))
264 {
265 ms_usbhost_msg("[ms_usb_associate_dev] Allocating failed\n");
266 return -ENOMEM;
267 }
268 return 0;
269 }
270
ms_usb_set_subclass(struct ms_usdata * ms_us,struct stUnusual_dev * unusual_dev,struct usb_interface_descriptor * idesc)271 static void ms_usb_set_subclass(struct ms_usdata *ms_us,struct stUnusual_dev *unusual_dev, struct usb_interface_descriptor *idesc)
272 {
273 if (unusual_dev->vendorName)
274 ms_usbhost_msg("[ms_usb_get_device_info] Vendor: %s\n", unusual_dev->vendorName);
275
276 if(unusual_dev->useProtocol == MS_DEVICE_SC)
277 ms_us->subclass = idesc->bInterfaceSubClass;
278 else
279 ms_us->subclass = unusual_dev->useProtocol;
280
281 if (strlen(ms_us->vendor) == 0)
282 {
283 if (unusual_dev->vendorName)
284 {
285 strncpy(ms_us->vendor, unusual_dev->vendorName, sizeof(ms_us->vendor)-1);
286 ms_us->vendor[sizeof(ms_us->vendor)-1] = '\0';
287 }
288 else
289 strncpy(ms_us->vendor, "Unknown", sizeof(ms_us->vendor));
290 }
291 }
292
ms_usb_set_protocol(struct ms_usdata * ms_us,struct stUnusual_dev * unusual_dev,struct usb_interface_descriptor * idesc)293 static void ms_usb_set_protocol(struct ms_usdata *ms_us,struct stUnusual_dev *unusual_dev, struct usb_interface_descriptor *idesc)
294 {
295 if (unusual_dev->productName)
296 ms_usbhost_msg("[ms_usb_get_device_info] Product: %s\n", unusual_dev->productName);
297
298 if(unusual_dev->useTransport == MS_DEVICE_PR)
299 ms_us->protocol = idesc->bInterfaceProtocol;
300 else
301 ms_us->protocol = unusual_dev->useTransport;
302
303 if (strlen(ms_us->product) == 0)
304 {
305 if (unusual_dev->productName)
306 {
307 strncpy(ms_us->product, unusual_dev->productName, sizeof(ms_us->product)-1);
308 ms_us->product[sizeof(ms_us->product)-1] = '\0';
309 }
310 else
311 strncpy(ms_us->product, "Unknown", sizeof(ms_us->product));
312 }
313 }
314
ms_usb_get_device_info(struct ms_usdata * ms_us,int idx)315 static void ms_usb_get_device_info(struct ms_usdata *ms_us, int idx)
316 {
317 struct usb_interface_descriptor *idesc =
318 &ms_us->pusb_intf->altsetting[ms_us->pusb_intf->act_altsetting].desc;
319 struct stUnusual_dev *unusual_dev = &MS_USB_unusual_dev_list[idx];
320
321 ms_us->unusual_dev = unusual_dev;
322 ms_us->flags = unusual_dev->flags;
323 ms_usb_set_subclass(ms_us,unusual_dev,idesc);
324 ms_usb_set_protocol(ms_us,unusual_dev,idesc);
325 }
326
ms_usb_get_transport(struct ms_usdata * ms_us)327 static int ms_usb_get_transport(struct ms_usdata *ms_us)
328 {
329 switch (ms_us->protocol)
330 {
331 case MS_CB_PR:
332 ms_usbhost_msg("CB Protocol\n");
333 ms_us->transport = ms_usb_CB_transport;
334 ms_us->transport_reset = ms_usb_CB_reset;
335 ms_us->max_lun = 0; //FIXME, Find some way to get real Max. LUN
336 break;
337 case MS_BULK_PR:
338 ms_usbhost_debug("BULK Protocol\n");
339 ms_us->transport = ms_usb_bulk_transport;
340 ms_us->transport_reset = ms_usb_bulk_reset;
341 break;
342 case MS_CBI_PR:
343 ms_usbhost_msg("Not support CBI Protocol..\n");
344 default:
345 return -EIO;
346 }
347 if (ms_us->flags & MS_SINGLE_LUN)
348 ms_us->max_lun = 0;
349 return 0;
350 }
351
ms_usb_get_protocol(struct ms_usdata * ms_us)352 static int ms_usb_get_protocol(struct ms_usdata *ms_us)
353 {
354 switch (ms_us->subclass)
355 {
356 case MS_RBC_SC:
357 ms_usbhost_msg("RBC Subclass\n");
358 ms_us->proto_handler = ms_usb_transparent_scsi_command;
359 break;
360 case MS_SFF_SC:
361 case MS_SCSI_SC:
362 case 0xFF: // For Sony DC P8 (P series) and Sony DV
363 ms_usbhost_debug("Transparent SCSI\n");
364 ms_us->proto_handler = ms_usb_transparent_scsi_command;
365 break;
366 case MS_ATAPI_SC:
367 ms_usbhost_msg("ATAPI Subclass\n");
368 ms_us->proto_handler = ms_usb_transparent_scsi_command;
369 ms_us->max_lun = 0;
370 break;
371 #if SupportOtherDevice
372 case MS_QIC_SC:
373 ms_usbhost_msg("QIC-157 Subclass\n");
374 ms_us->proto_handler = ms_usb_qic157_command;
375 ms_us->max_lun = 0;
376 break;
377 case MS_UFI_SC:
378 ms_usbhost_msg("UFI Subclass\n");
379 ms_us->proto_handler = ms_usb_ufi_command;
380 break;
381 #endif
382 default:
383 return -EIO;
384 }
385 return 0;
386 }
387
ms_usb_set_pipe(struct ms_usdata * ms_us,struct usb_endpoint_descriptor * ep_in,struct usb_endpoint_descriptor * ep_out,struct usb_endpoint_descriptor * ep_int)388 static void ms_usb_set_pipe(struct ms_usdata *ms_us,
389 struct usb_endpoint_descriptor *ep_in,
390 struct usb_endpoint_descriptor *ep_out,
391 struct usb_endpoint_descriptor *ep_int)
392 {
393 ms_us->ctrl_send_pipe = usb_sndctrlpipe(ms_us->pusb_dev, 0);
394 ms_us->ctrl_recv_pipe = usb_rcvctrlpipe(ms_us->pusb_dev, 0);
395 ms_us->bulk_send_pipe = usb_sndbulkpipe(ms_us->pusb_dev, ep_out->bEndpointAddress & USB_ENDPOINT_NUMBER_MASK);
396 ms_us->bulk_recv_pipe = usb_rcvbulkpipe(ms_us->pusb_dev, ep_in->bEndpointAddress & USB_ENDPOINT_NUMBER_MASK);
397 if (ep_int)
398 {
399 ms_us->int_recv_pipe = usb_rcvbulkpipe(ms_us->pusb_dev,
400 ep_int->bEndpointAddress & USB_ENDPOINT_NUMBER_MASK);
401 ms_us->bInterval_ep = ep_int->bInterval;
402 }
403 }
404
ms_usb_get_pipes(struct ms_usdata * ms_us)405 static int ms_usb_get_pipes(struct ms_usdata *ms_us)
406 {
407 int tmp;
408
409 struct usb_host_interface *altsetting =&ms_us->pusb_intf->altsetting[ms_us->pusb_intf->act_altsetting];
410 struct usb_endpoint_descriptor *ep_tmp;
411 struct usb_endpoint_descriptor *ep_in = NULL;
412 struct usb_endpoint_descriptor *ep_out = NULL;
413 struct usb_endpoint_descriptor *ep_int = NULL;
414
415 for (tmp = 0; tmp < altsetting->desc.bNumEndpoints; tmp++)
416 {
417 ep_tmp=&altsetting->endpoint[tmp].desc;
418 if ((ep_tmp->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) == USB_ENDPOINT_XFER_BULK)
419 {
420 if (ep_tmp->bEndpointAddress & USB_DIR_IN)
421 ep_in = ep_tmp;
422 else
423 ep_out = ep_tmp;
424 }
425 else if ((ep_tmp->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) == USB_ENDPOINT_XFER_INT)
426 ep_int = ep_tmp;
427 }
428 if (!ep_in || !ep_out || (ms_us->protocol == MS_CBI_PR && !ep_int))
429 {
430 ms_usbhost_msg("EP sanity check failed! Rejecting dev.\n");
431 return -EIO;
432 }
433
434 ms_usb_set_pipe(ms_us,ep_in,ep_out,ep_tmp);
435
436 return 0;
437 }
438
ms_usb_acquire_resources(struct ms_usdata * ms_us)439 static int ms_usb_acquire_resources(struct ms_usdata *ms_us)
440 {
441 int regval;
442
443 ms_us->current_urb = ms_usb_alloc_urb(GFP_KERNEL);
444 //ms_us->data_urb = ms_usb_alloc_urb(GFP_KERNEL);
445 //ms_us->status_urb = ms_usb_alloc_urb(GFP_KERNEL);
446 if((!ms_us->current_urb)/* || (!ms_us->data_urb) || (!ms_us->status_urb)*/)
447 {
448 ms_usbhost_err("USB Request Block allocates failed\n");
449 return -ENOMEM;
450 }
451 //osapi_down(&ms_us->dev_semaphore);
452 osapi_mutex_lock(ms_us->dev_mutex);
453 if (ms_us->protocol == MS_BULK_PR)
454 {
455 regval = ms_usb_control_msg(ms_us, ms_us->ctrl_recv_pipe, BULK_GET_MAX_LUN,
456 USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_INTERFACE,
457 0, ms_us->ifnum, ms_us->iobuf, 1, HZ*5);
458
459 ms_usbhost_debug("GetMaxLUN command regval is %d, data is %d\n", regval, ms_us->iobuf[0]);
460
461 if (regval == 1)
462 ms_us->max_lun = ms_us->iobuf[0];
463 else
464 ms_us->max_lun = 0;
465 }
466
467 ms_us->msc_device=(struct LUN_Device*)kmalloc(sizeof(struct LUN_Device)*(ms_us->max_lun+1), GFP_KERNEL);
468 memset(ms_us->msc_device,0 , sizeof(struct LUN_Device)*(ms_us->max_lun+1));
469 if (ms_us->unusual_dev->initFunction)
470 ms_us->unusual_dev->initFunction(ms_us);
471
472 //osapi_up(&ms_us->dev_semaphore);
473 osapi_mutex_unlock(ms_us->dev_mutex);
474 //ms_us->usb_state = IDLE_STATE;
475
476 return 0;
477 }
478
ms_usb_unregister_dev(struct ms_usdata * ms_us)479 static void ms_usb_unregister_dev(struct ms_usdata *ms_us)
480 {
481 MS_U8 u8Lun;
482
483 //osapi_down(&ms_us->dev_semaphore);
484 osapi_mutex_lock(ms_us->dev_mutex);
485 if (ms_us->cr)
486 {
487 ms_usb_buffer_free(ms_us->pusb_dev, sizeof(*ms_us->cr), ms_us->cr, ms_us->cr_dma);
488 ms_us->cr = NULL;
489 }
490 if (ms_us->iobuf)
491 {
492 ms_usb_buffer_free(ms_us->pusb_dev, MS_IOBUF_SIZE, ms_us->iobuf, ms_us->iobuf_dma);
493 ms_us->iobuf = NULL;
494 }
495 ms_usb_set_intfdata(ms_us->pusb_intf, NULL);
496 ms_usb_put_dev(ms_us->pusb_dev);
497 ms_us->pusb_dev = NULL;
498 ms_us->pusb_intf = NULL;
499 //osapi_up(&ms_us->dev_semaphore); // if ms_us to be protected, unlock later
500
501 if (ms_us->extra_destructor)
502 {
503 ms_usbhost_msg("--> Call extra_destructor()\n");
504 ms_us->extra_destructor(ms_us->extra);
505 }
506 if (ms_us->extra)
507 kfree(ms_us->extra);
508 if (ms_us->current_urb)
509 ms_usb_free_urb(ms_us->current_urb);
510 //if (ms_us->data_urb)
511 // ms_usb_free_urb(ms_us->data_urb);
512 //if (ms_us->status_urb)
513 // ms_usb_free_urb(ms_us->status_urb);
514
515 for (u8Lun=0; u8Lun<=ms_us->max_lun; u8Lun++)
516 if (ms_us->msc_device[u8Lun].bFSInit)
517 RemoveUSBDiskPort(ms_us->ustor_id, u8Lun);
518 Mass_stor_us[ms_us->ustor_id] = NULL;
519
520 if (ms_us->msc_device)
521 kfree(ms_us->msc_device);
522
523 osapi_mutex_unlock(ms_us->dev_mutex);
524 osapi_mutex_delete(ms_us->dev_mutex);
525 kfree(ms_us);
526 }
527
ms_usb_msc_probe(struct usb_interface * ms_intf,const struct usb_device_id * id)528 static int ms_usb_msc_probe(struct usb_interface *ms_intf, const struct usb_device_id *id)
529 {
530 struct ms_usdata *ms_us;
531 const int idx = id - MSC_usb_ids;
532 int regval,tmp,i;
533 struct usb_device *pudev;
534 unsigned char startId;
535
536 ms_usbhost_debug("USB MSC device detected\n");
537 ms_usbhost_debug("act_altsetting = %d, idx = %d\n", ms_intf->act_altsetting, idx);
538 ms_us = (struct ms_usdata *) kmalloc(sizeof(*ms_us), GFP_KERNEL);
539 if (!ms_us)
540 {
541 ms_usbhost_msg("Out of memory %d\n", ms_us);
542 return -ENOMEM;
543 }
544
545 memset(ms_us, 0, sizeof(struct ms_usdata));
546 //osapi_init_MUTEX(&(ms_us->dev_semaphore));
547 osapi_mutex_init(ms_us->dev_mutex, "US_MUTEX");
548 //osapi_init_MUTEX_LOCKED(&(ms_us->sema));
549 //init_completion(&(ms_us->notify));
550
551 regval = ms_usb_associate_dev(ms_us, ms_intf);
552 if (regval)
553 {
554 ms_usb_unregister_dev(ms_us);
555 return regval;
556 }
557
558 ms_usb_get_device_info(ms_us, idx);
559 if (strlen(ms_us->serial) == 0)
560 strncpy(ms_us->serial, "None", sizeof(ms_us->serial));
561
562 regval = ms_usb_get_transport(ms_us);
563 if (regval)
564 {
565 ms_usb_unregister_dev(ms_us);
566 return regval;
567 }
568 regval = ms_usb_get_protocol(ms_us);
569 if (regval)
570 {
571 ms_usb_unregister_dev(ms_us);
572 return regval;
573 }
574 regval = ms_usb_get_pipes(ms_us);
575 if (regval)
576 {
577 ms_usb_unregister_dev(ms_us);
578 return regval;
579 }
580 regval = ms_usb_acquire_resources(ms_us);
581 if (regval)
582 {
583 ms_usb_unregister_dev(ms_us);
584 return regval;
585 }
586
587 pudev = interface_to_usbdev(ms_intf);
588
589 startId = (MAX_USTOR* (((struct usb_hcd *)pudev->bus->hcpriv)->host_id));
590 USB_ASSERT(startId < NUM_OF_ROOT_HUB*MAX_USTOR, "startId >= NUM_OF_ROOT_HUB*MAX_USTOR\n");
591
592 tmp = (-1);
593 for (i=startId; i<startId+MAX_USTOR; i++)
594 {
595 if (Mass_stor_us[i] == NULL)
596 tmp = i; // the result sequence 7,6,5...
597 }
598
599 //ERROR: Exceed the max support number of usb storage device !!
600 if (tmp != (-1))
601 {
602 Mass_stor_us[tmp] = ms_us;
603 ms_us->ustor_id = (unsigned char)tmp;
604 }
605 else
606 {
607 ms_usbhost_err("MSC: exceed the max number of support devices!!!\n");
608 ms_usb_unregister_dev(ms_us);
609 return -ENOBUFS;
610 }
611
612 ms_us->host_id = ((struct usb_hcd *)pudev->bus->hcpriv)->host_id;
613 for(tmp = 0; tmp<=ms_us->max_lun; tmp++)
614 ms_us->msc_device[tmp].bDeviceReady = FALSE;
615
616 ms_usbhost_msg("find USB MSC device at device number %d\n", ms_us->pusb_dev->u32DevNum);
617
618 return 0;
619 }
620
ms_usb_msc_disconnect(struct usb_interface * ms_intf)621 static void ms_usb_msc_disconnect(struct usb_interface *ms_intf)
622 {
623 struct ms_usdata *ms_us = (struct ms_usdata*) ms_usb_get_intfdata(ms_intf);
624
625 ms_usbhost_msg("MSC disconnect id: %d, us->flag %x \n", ms_us->ustor_id, ms_us->flags);
626 ms_set_bit(MS_IDX_DISCONNECTING, &ms_us->flags, unsigned long);
627 if (ms_test_and_clear_bit(MS_IDX_URB_ACTIVE, &ms_us->flags))
628 {
629 ms_usbhost_err("[MSCDIS]--> cancel USB request block\n");
630 ms_usb_unlink_urb(ms_us->current_urb);
631 }
632 ms_usb_unregister_dev(ms_us);
633 }
634
ms_ioctl_issue_ctrl(struct ms_usdata * ms_us,void * pData)635 int ms_ioctl_issue_ctrl(struct ms_usdata *ms_us, void *pData)
636 {
637 struct usb_ioctl_ctrl_xfer *pCtrlData = (struct usb_ioctl_ctrl_xfer*)pData;
638 int retval = -1;
639
640 ms_usbhost_msg("[USB] control urb: bRequestType=%02x "
641 "bRequest=%02x wValue=%04x "
642 "wIndex=%04x wLength=%04x\n",
643 pCtrlData->bRequestType,
644 pCtrlData->bRequest,
645 pCtrlData->wValue,
646 pCtrlData->wIndex,
647 pCtrlData->wLength);
648
649 if((pCtrlData->wLength > 0) && ((pCtrlData->bRequestType & USB_DIR_IN) == 0)) /* OUT transfer */
650 memcpy(ms_us->iobuf, pCtrlData->pDataBuf, pCtrlData->wLength);
651
652 retval = ms_usb_control_msg(ms_us, ms_us->ctrl_recv_pipe,
653 pCtrlData->bRequest,
654 pCtrlData->bRequestType,
655 pCtrlData->wValue,
656 pCtrlData->wIndex,
657 ms_us->iobuf,
658 pCtrlData->wLength,
659 (pCtrlData->timeout*HZ)/1000);
660
661 ms_usbhost_msg("[USB] ctrl ioctl reault: %d\n", retval);
662
663 if(retval < 0)
664 {
665 goto done;
666 }
667
668 if((pCtrlData->wLength > 0) && (pCtrlData->bRequestType & USB_DIR_IN)) /* IN transfer */
669 memcpy(pCtrlData->pDataBuf, ms_us->iobuf, pCtrlData->wLength);
670
671 done:
672 return retval;
673 }
674
ms_ioctl_issue_bulk(struct ms_usdata * ms_us,void * pData)675 int ms_ioctl_issue_bulk(struct ms_usdata *ms_us, void *pData)
676 {
677 struct usb_ioctl_bulk_xfer *pBulkData = (struct usb_ioctl_bulk_xfer*)pData;
678 int retval = -1;
679 U32 act_len = 0;
680 U32 pipe;
681
682 ms_usbhost_msg("[USB] bulk urb: dir=%02x "
683 "len=%02x timeout=%04x\n",
684 pBulkData->dir,
685 pBulkData->len);
686
687 pipe = (pBulkData->dir == USB_IOCTL_BULK_OUT) ? ms_us->bulk_send_pipe : ms_us->bulk_recv_pipe;
688
689 retval = ms_usb_bulk_transfer_buf(ms_us, pipe, pBulkData->pDataBuf, pBulkData->len, &act_len);
690
691 if(retval == 0)
692 {
693 retval = act_len;
694 }
695
696 return retval;
697 }
698
699 #define DECLARE_VID_PID(VID, PID) (((U32)VID & 0xFFFF) << 16 | ((U32)PID & 0xFFFF))
700 #define QUIRK_TABLE_TERMINATOR DECLARE_VID_PID(0x0000, 0x0000)
701 #define QUIRK_NULL_FLAG 0x00000000UL
702
703 struct quirk {
704 U32 vid_pid;
705 U32 flag;
706 };
707
708 #define QUIRK_NUMMAX 20
709
710 struct quirk quirk_list[QUIRK_NUMMAX];
711 int quirk_num;
712
quirk_list_init(void)713 void quirk_list_init(void)
714 {
715 int i;
716
717 diag_printf("[USB] quirk list init, support max %d\n", QUIRK_NUMMAX);
718 quirk_num = 0;
719
720 for(i = 0;i < QUIRK_NUMMAX; i++)
721 {
722 quirk_list[i].vid_pid = QUIRK_TABLE_TERMINATOR;
723 quirk_list[i].flag = QUIRK_NULL_FLAG;
724 }
725 }
726
quirk_list_add(U32 vid_pid,U32 flag)727 int quirk_list_add(U32 vid_pid, U32 flag)
728 {
729 int retval = -1;
730
731 if(quirk_num < QUIRK_NUMMAX)
732 {
733 quirk_list[quirk_num].vid_pid = vid_pid;
734 quirk_list[quirk_num].flag = flag;
735
736 diag_printf("[USB] quirk(%d) add vid/pid 0x%x flag 0x%x\n", quirk_num, vid_pid, flag);
737 quirk_num++;
738 retval = 0;
739 }
740 else
741 {
742 diag_printf("[USB] quirk num overrun, max(%d)\n", QUIRK_NUMMAX);
743 retval = -1;
744 }
745 return retval;
746 }
747
quirk_list_add_3g(U32 vid_pid)748 int quirk_list_add_3g(U32 vid_pid)
749 {
750 return quirk_list_add(vid_pid, QUIRK_IGNORE_TUR | QUIRK_IGNORE_CD_ROM | QUIRK_IGNORE_RD_CAP | QUIRK_IGNORE_MOD_SENSE);
751 }
752
quirk_bypass_stage(struct ms_usdata * ms_us,U32 stage_flag)753 bool quirk_bypass_stage(struct ms_usdata *ms_us, U32 stage_flag)
754 {
755 U32 vid_pid = DECLARE_VID_PID(ms_us->pusb_dev->descriptor.idVendor, ms_us->pusb_dev->descriptor.idProduct);
756 int iter;
757
758 iter = 0;
759
760 while(iter < QUIRK_NUMMAX && quirk_list[iter].vid_pid != QUIRK_TABLE_TERMINATOR)
761 {
762 if((vid_pid == quirk_list[iter].vid_pid) && (quirk_list[iter].flag & stage_flag))
763 {
764 diag_printf("[USB] quirk bypass stage(0x%x) (VID_PID=0x%x)\n", stage_flag, vid_pid);
765 return true;
766 }
767 iter++;
768 }
769 return false;
770 }
771