xref: /utopia/UTPA2-700.0.x/modules/usb/drv/usb_ecos/newhost/drvMassStor.c (revision 53ee8cc121a030b8d368113ac3e966b4705770ef)
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