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 #include <cyg/infra/cyg_type.h>
80 #include <cyg/infra/cyg_ass.h>
81 #include <cyg/infra/diag.h>
82 #include <cyg/hal/hal_arch.h>
83 #include <cyg/hal/hal_io.h>
84 #include <cyg/hal/drv_api.h>
85 #include <cyg/io/io.h>
86 #include <cyg/io/devtab.h>
87 #include <cyg/io/disk.h>
88
89 #include "drvSCSI.h"
90 #include "drvMassStor.h"
91 #include "drvUSB.h"
92 //#include <pkgconf/devs_usb.h>
93
94 extern void RemoveUSBDiskPort(U8 uPort, U8 uLunNum);
95 //#define USB_DISK_DBG 1
96
97 typedef struct {
98 int num;
99 cyg_uint32 size;
100 int uPort;
101 int DevId;
102 } usb_disk_info_t;
103
104 // ----------------------------------------------------------------------------
105 #ifndef __lint__ //NOTE: lint will complain for the following device tables..
106 static bool usb_disk_init(struct cyg_devtab_entry *tab);
107
108 static Cyg_ErrNo usb_disk_read(disk_channel *chan,
109 void *buf,
110 cyg_uint32 len,
111 cyg_uint32 block_num);
112
113 static Cyg_ErrNo usb_disk_write(disk_channel *chan,
114 const void *buf,
115 cyg_uint32 len,
116 cyg_uint32 block_num);
117
118 static Cyg_ErrNo usb_disk_get_config(disk_channel *chan,
119 cyg_uint32 key,
120 const void *xbuf,
121 cyg_uint32 *len);
122
123 static Cyg_ErrNo usb_disk_set_config(disk_channel *chan,
124 cyg_uint32 key,
125 const void *xbuf,
126 cyg_uint32 *len);
127
128 static Cyg_ErrNo usb_disk_lookup(struct cyg_devtab_entry **tab,
129 struct cyg_devtab_entry *sub_tab,
130 const char *name);
131
132 static struct DISK_FUNS(usb_disk_funs,
133 &usb_disk_read,
134 &usb_disk_write,
135 &usb_disk_get_config,
136 &usb_disk_set_config
137 );
138
139 //USB_2
140 // We define 10 empty block device entries for our USB storage device.
141 // Initially, these entries can not be used until the USB module connect it.
142 #if 1
143 #define USB_DISK_INSTANCE(_number_,_port_,_name_) \
144 static usb_disk_info_t usb_disk_info##_port_##_number_ = { \
145 -1, \
146 0, \
147 -1, \
148 -1 \
149 }; \
150 disk_controller usb_disk_controller##_port_##_number_ = { \
151 priv: NULL, \
152 init: false, \
153 busy: false \
154 }; \
155 DISK_CHANNEL(usb_disk_channel##_port_##_number_, \
156 usb_disk_funs, \
157 usb_disk_info##_port_##_number_, \
158 usb_disk_controller##_port_##_number_, \
159 true \
160 ); \
161 BLOCK_DEVTAB_ENTRY(usb_disk_io##_port_##_number_, \
162 _name_, \
163 0, \
164 &cyg_io_disk_devio, \
165 &usb_disk_init, \
166 &usb_disk_lookup, \
167 &usb_disk_channel##_port_##_number_ \
168 );
169 #else
170 #define USB_DISK_INSTANCE(_number_,_port_,_name_) \
171 static usb_disk_info_t usb_disk_info##_port_##_number_ = { \
172 num: _number_, \
173 size: 0, \
174 uPort: _port_ , \
175 DevId: -1 \
176 }; \
177 disk_controller usb_disk_controller##_port_##_number_ = { \
178 priv: NULL, \
179 init: false, \
180 busy: false \
181 }; \
182 DISK_CHANNEL(usb_disk_channel##_port_##_number_, \
183 usb_disk_funs, \
184 usb_disk_info##_port_##_number_, \
185 usb_disk_controller##_port_##_number_, \
186 true \
187 ); \
188 BLOCK_DEVTAB_ENTRY(usb_disk_io##_port_##_number_, \
189 _name_, \
190 0, \
191 &cyg_io_disk_devio, \
192 &usb_disk_init, \
193 &usb_disk_lookup, \
194 &usb_disk_channel##_port_##_number_ \
195 );
196 #endif
197
198 USB_DISK_INSTANCE(0, 0, "/dev/sda/");
199 USB_DISK_INSTANCE(1, 0, "/dev/sdb/");
200 USB_DISK_INSTANCE(2, 0, "/dev/sdc/");
201 USB_DISK_INSTANCE(3, 0, "/dev/sdd/");
202 USB_DISK_INSTANCE(4, 0, "/dev/sde/");
203 USB_DISK_INSTANCE(5, 0, "/dev/sdf/");
204 USB_DISK_INSTANCE(6, 0, "/dev/sdg/");
205 USB_DISK_INSTANCE(7, 0, "/dev/sdh/");
206
207 USB_DISK_INSTANCE(0, 1, "/dev/sdi/");
208 USB_DISK_INSTANCE(1, 1, "/dev/sdj/");
209 USB_DISK_INSTANCE(2, 1, "/dev/sdk/");
210 USB_DISK_INSTANCE(3, 1, "/dev/sdl/");
211 USB_DISK_INSTANCE(4, 1, "/dev/sdm/");
212 USB_DISK_INSTANCE(5, 1, "/dev/sdn/");
213 USB_DISK_INSTANCE(6, 1, "/dev/sdo/");
214 USB_DISK_INSTANCE(7, 1, "/dev/sdp/");
215
216 USB_DISK_INSTANCE(0, 2, "/dev/sdq/");
217 USB_DISK_INSTANCE(1, 2, "/dev/sdr/");
218 USB_DISK_INSTANCE(2, 2, "/dev/sds/");
219 USB_DISK_INSTANCE(3, 2, "/dev/sdt/");
220 USB_DISK_INSTANCE(4, 2, "/dev/sdu/");
221 USB_DISK_INSTANCE(5, 2, "/dev/sdv/");
222 USB_DISK_INSTANCE(6, 2, "/dev/sdw/");
223 USB_DISK_INSTANCE(7, 2, "/dev/sdx/");
224
225 #ifdef _USB_DISK_DEBUG
dump_data(cyg_uint8 * buf,cyg_uint32 len)226 void dump_data(cyg_uint8 *buf, cyg_uint32 len)
227 {
228 int i, j=0;
229
230 while(j<len)
231 {
232 diag_printf("[ ");
233 for (i=0; i<16; i++)
234 diag_printf("%x ", buf[j+i]);
235 diag_printf(" ]\n");
236 j+=i;
237 }
238
239 }
240 #endif
241
242 static bool
usb_disk_init(struct cyg_devtab_entry * tab)243 usb_disk_init(struct cyg_devtab_entry *tab)
244 {
245 disk_channel *chan = (disk_channel *) tab->priv;
246 cyg_disk_info_t *info = chan->info;
247
248 info->connected = false;
249 chan->valid = false;
250
251 if (chan->init)
252 return true;
253
254
255 //if (!(chan->callbacks->disk_init)(tab))
256 // return false;
257
258 // Initially, we declare that we are not connected
259 info->connected = false;
260 chan->valid = false;
261
262 return true;
263 }
264
265 static Cyg_ErrNo
usb_disk_lookup(struct cyg_devtab_entry ** tab,struct cyg_devtab_entry * sub_tab,const char * name)266 usb_disk_lookup(struct cyg_devtab_entry **tab,
267 struct cyg_devtab_entry *sub_tab,
268 const char *name)
269 {
270 disk_channel *chan = (disk_channel *) (*tab)->priv;
271 return (chan->callbacks->disk_lookup(tab, sub_tab, name));
272 }
273
274 static Cyg_ErrNo
usb_disk_read(disk_channel * chan,void * buf,cyg_uint32 len,cyg_uint32 block_num)275 usb_disk_read(disk_channel *chan,
276 void *buf,
277 cyg_uint32 len,
278 cyg_uint32 block_num)
279 {
280 usb_disk_info_t *usb_info = (usb_disk_info_t *)chan->dev_priv;
281
282 if ((usb_info->uPort == -1) ||
283 (usb_info->num == -1) ||
284 (usb_info->DevId == -1) )
285 {
286 diag_printf("Err: usb_disk_read: device not exist \n");
287 return ENODEV;
288 }
289
290 if (bSCSI_Read_10(usb_info->uPort, usb_info->num, block_num,
291 len , (cyg_uint8*)buf) )
292 {
293 #ifdef _USB_DISK_DEBUG
294 diag_printf("[%s][%d] ==============================\n", __FUNCTION__, __LINE__);
295 diag_printf("[%s][%d] %d %d %d %d 0x%08x\n", __FUNCTION__, __LINE__,
296 usb_info->uPort, usb_info->num, block_num, len , (int)buf);
297 dump_data(buf, len* 512);
298 diag_printf("[%s][%d] ==============================\n", __FUNCTION__, __LINE__);
299 #endif
300
301 return ENOERR;
302 }
303 else
304
305 return -EIO;
306 }
307
308 static Cyg_ErrNo
usb_disk_write(disk_channel * chan,const void * buf,cyg_uint32 len,cyg_uint32 block_num)309 usb_disk_write(disk_channel *chan,
310 const void *buf,
311 cyg_uint32 len,
312 cyg_uint32 block_num)
313 {
314 usb_disk_info_t *usb_info = (usb_disk_info_t *)chan->dev_priv;
315
316 if ((usb_info->uPort == -1) ||
317 (usb_info->num == -1) ||
318 (usb_info->DevId == -1) )
319 {
320 diag_printf("Err: usb_disk_read: device not exist \n");
321 return ENODEV;
322 }
323
324 //kevinhuang, no write temporarily coz current FATFS will contaminate FS on the disk
325 if (bSCSI_Write_10(usb_info->uPort, usb_info->num, block_num,
326 len, (cyg_uint8*) buf) )
327 return ENOERR;
328 else
329 return -EIO;
330 }
331
332 static Cyg_ErrNo
usb_disk_get_config(disk_channel * chan,cyg_uint32 key,const void * xbuf,cyg_uint32 * len)333 usb_disk_get_config(disk_channel *chan,
334 cyg_uint32 key,
335 const void *xbuf,
336 cyg_uint32 *len)
337 {
338
339
340 return -EINVAL;
341 }
342
343 static Cyg_ErrNo
usb_disk_set_config(disk_channel * chan,cyg_uint32 key,const void * xbuf,cyg_uint32 * len)344 usb_disk_set_config(disk_channel *chan,
345 cyg_uint32 key,
346 const void *xbuf,
347 cyg_uint32 *len)
348 {
349 Cyg_ErrNo result = ENOERR;
350 // cyg_mmc_bus_device* disk = (cyg_mmc_bus_device*) chan->dev_priv;
351 // cyg_disk_info_t *info = chan->info;
352
353 switch(key)
354 {
355 case CYG_IO_SET_CONFIG_DISK_MOUNT:
356 // There will have been a successful lookup(), so there's
357 // little point in checking the disk again.
358 // if ((sd_chk_ready()!=_DEVICE_READY)&&
359 // result=-EINVAL;
360 //else device is OK
361
362 break;
363
364 case CYG_IO_SET_CONFIG_DISK_UMOUNT:
365 if (0 == chan->info->mounts)
366 {
367 //cyg_mmc_bus* bus = disk->mmc_bus_dev;
368
369 // If this is the last unmount of the card, mark it as
370 // disconnected. If the user then removes the card and
371 // plugs in a new one everything works cleanly.
372 // disk->mmc_connected = false;
373 // info->connected = false;
374 //result = (chan->callbacks->disk_disconnected)(chan);
375
376 // * deselect it too if it had been selected * //
377 // * We don't care about any error really. This device is going away. * //
378 //mmc_bus_select_card( bus, NULL );
379 }
380 break;
381 }
382
383 return result;
384 // return -EINVAL;
385
386 }
387 #endif
388
389 extern struct us_data *Mass_stor_us[];
MDrv_USB_MscLookupHostID(char * str)390 U8 MDrv_USB_MscLookupHostID(char *str)
391 {
392 cyg_devtab_entry_t *t;
393 disk_channel *chan;
394 usb_disk_info_t *p_usb_info;
395 U8 host_id = 0xff;
396
397 for (t = &__DEVTAB__[0]; t != &__DEVTAB_END__; t++)
398 {
399 chan = (disk_channel *) t->priv;
400 if (chan == NULL)
401 continue;
402 p_usb_info = (usb_disk_info_t *) chan->dev_priv;
403 if (p_usb_info == NULL)
404 continue;
405
406 if ((p_usb_info->DevId != (-1)) && (strcmp(str, t->name) == 0)) // find the table entry
407 {
408 host_id = Mass_stor_us[p_usb_info->uPort]->host_id;
409 break;
410 }
411 }
412 if (host_id == 0xff)
413 diag_printf("Not found %s on any USB host port\n", str);
414 return (host_id);
415 }
416
MDrv_USB_MscLookupProductString(char * str)417 char *MDrv_USB_MscLookupProductString(char *str)
418 {
419 cyg_devtab_entry_t *t;
420 disk_channel *chan;
421 usb_disk_info_t *p_usb_info;
422 char *pstr;
423
424 pstr = NULL;
425 for (t = &__DEVTAB__[0]; t != &__DEVTAB_END__; t++)
426 {
427 chan = (disk_channel *) t->priv;
428 if (chan == NULL)
429 continue;
430 p_usb_info = (usb_disk_info_t *) chan->dev_priv;
431 if (p_usb_info == NULL)
432 continue;
433
434 if ((p_usb_info->DevId != (-1)) && (strcmp(str, t->name) == 0)) // find the table entry
435 {
436 pstr = Mass_stor_us[p_usb_info->uPort]->pusb_dev->product;
437 break;
438 }
439 }
440 if (pstr == NULL)
441 diag_printf("Product string not found\n");
442 return (pstr);
443 }
444
ConnectUSBDisk(U8 uPort,U8 uLunNum)445 BOOL ConnectUSBDisk(U8 uPort, U8 uLunNum)
446 {
447 struct LUN_Device *LunDevice = Mass_stor_us[uPort]->Mass_stor_device;
448 // Cyg_ErrNo err;
449 cyg_devtab_entry_t *dev_h;
450 // cyg_io_handle_t io_h;
451 disk_channel *chan;
452 usb_disk_info_t *p_usb_info;
453 cyg_disk_identify_t ident;
454 cyg_devtab_entry_t *t;
455 char szUSBDevName[12]={0};
456 //int ret;
457
458 for (t = &__DEVTAB__[0]; t != &__DEVTAB_END__; t++)
459 {
460 chan = (disk_channel *) t->priv;
461 if (chan == NULL)
462 continue;
463 p_usb_info = (usb_disk_info_t *) chan->dev_priv;
464 if (p_usb_info == NULL)
465 continue;
466 if (p_usb_info->DevId == ((uPort+1)*MAX_USB_STOR_LUNS + uLunNum) )
467 {
468 diag_printf("Warning : find one previous device here !!\n");
469 //call RemoveUSBDiskPort()???
470 RemoveUSBDiskPort(uPort, uLunNum);
471 p_usb_info->DevId = -1;
472 }
473 }
474
475 for (t = &__DEVTAB__[0]; t != &__DEVTAB_END__; t++)
476 {
477
478 chan = (disk_channel *) t->priv;
479 if (chan == NULL)
480 continue;
481 p_usb_info = (usb_disk_info_t *) chan->dev_priv;
482 if (p_usb_info == NULL)
483 continue;
484
485 if (p_usb_info->DevId == (-1))
486 {
487 p_usb_info->DevId = (uPort+1)*MAX_USB_STOR_LUNS + uLunNum;
488 break;
489 }
490 }
491
492 if (t == &__DEVTAB_END__)
493 {
494 diag_printf("Error! Can't find available disk name. Exceed maximum support number!\n");
495 return FALSE;
496 }
497
498 chan = (disk_channel *) t->priv;
499 chan->info->connected = true;
500
501 #if 0
502 szUSBDevName[7] = t->name[7];
503 diag_printf("cyg_io_lookup %s ..", szUSBDevName);
504
505 err = cyg_io_lookup(szUSBDevName, &io_h);
506 if (err != ENOERR)
507 {
508 diag_printf(" FALSE !!\n");
509 return FALSE;
510 }
511 diag_printf(" OK\n");
512
513 dev_h = (cyg_devtab_entry_t *) io_h;
514 #endif
515
516 dev_h = t;
517
518 chan = (disk_channel*) dev_h->priv;
519 p_usb_info = (usb_disk_info_t *) chan->dev_priv;
520 p_usb_info->uPort = uPort;
521 p_usb_info->num = uLunNum;
522
523 ident.serial[0] = '\0';
524 ident.firmware_rev[0] = '\0';
525 ident.model_num[0] = '\0';
526 // ident.lba_sectors_num = usb_info->size / 512;
527 ident.lba_sectors_num = LunDevice[uLunNum].u32BlockTotalNum;
528 ident.cylinders_num = 0;
529 ident.heads_num = 0;
530 ident.sectors_num = 0;
531 ident.phys_block_size = LunDevice[uLunNum].u32BlockSize;
532 ident.max_transfer = LunDevice[uLunNum].u32BlockSize;// 512;
533
534 //diag_printf("Connect USB disk %s\n", szUSBDevName);
535 diag_printf("Connect USB disk %s\n", dev_h->name);
536 diag_printf("Port:%d Lun:%d Id:%d\n", p_usb_info->uPort, p_usb_info->num, p_usb_info->DevId);
537 if (!(chan->callbacks->disk_init)(dev_h))
538 return FALSE;
539
540 if (ENOERR != (chan->callbacks->disk_connected)(dev_h, &ident))
541 return FALSE;
542
543 if ( _DrvUSB_CBFun != NULL )
544 {
545 if (strlen(dev_h->name) < 12)
546 strcpy(szUSBDevName, dev_h->name);
547 _DrvUSB_CBFun(USB_PLUG_IN, USB_EVENT_DEV_TYPE_STOR, szUSBDevName);
548 }
549 //Test
550 //ret = mount("/dev/sda/1", "/", "fatfs");
551 //diag_printf("mount status : %d \n", ret);
552 diag_printf("@@ Host ID %x\n", MDrv_USB_MscLookupHostID(szUSBDevName));
553
554 return TRUE;
555 }
556
RemoveUSBDiskPort(U8 uPort,U8 uLunNum)557 VOID RemoveUSBDiskPort(U8 uPort, U8 uLunNum)
558 {
559 // Cyg_ErrNo err;
560 cyg_devtab_entry_t *dev_h, *t;
561 // cyg_io_handle_t io_h;
562 disk_channel *chan;
563 cyg_disk_info_t *info;
564 usb_disk_info_t *p_usb_info;
565 char szUSBDevName[12]={0};
566 ///struct LUN_Device* LunDevice = Mass_stor_us[uPort]->Mass_stor_device;
567
568
569 #if 0
570 //UTL_snprintf(szUSBDevName, 12, "/dev/sd%c/", 'a' + uLunNum);
571 szUSBDevName[7]= 'a' + (uPort * MAX_USB_STOR_LUNS) + uLunNum;
572
573 err = cyg_io_lookup(szUSBDevName, &io_h);
574 if (err != ENOERR)
575 return;
576 dev_h = (cyg_devtab_entry_t *) io_h;
577 #endif
578
579 for (t = &__DEVTAB__[0]; t != &__DEVTAB_END__; t++)
580 {
581
582 chan = (disk_channel *) t->priv;
583 if (chan == NULL)
584 continue;
585 p_usb_info = (usb_disk_info_t *) chan->dev_priv;
586 if (p_usb_info == NULL)
587 continue;
588
589 if (p_usb_info->DevId == ((uPort+1)*MAX_USB_STOR_LUNS + uLunNum))
590 {
591 if ((p_usb_info->uPort != uPort) || (p_usb_info->num != uLunNum))
592 {
593 diag_printf("Warning: RemoveUSBDiskPort not match !!\n");
594 diag_printf("[Port lun]: [%d %d]->[%d %d]\n", uPort,uLunNum,p_usb_info->uPort,p_usb_info->num);
595 }
596 diag_printf("RemoveUSBDiskPort:%d %d %d\n",p_usb_info->uPort,p_usb_info->num,p_usb_info->DevId);
597 break;
598 }
599 }
600
601 if (t == &__DEVTAB_END__)
602 {
603 diag_printf("RemoveUSBDiskPort: Can't find match Port:%d Lun:%d\n", uPort, uLunNum);
604 return;
605 }
606
607 dev_h = t;
608 chan = (disk_channel *) dev_h->priv;
609 info = chan->info;
610 p_usb_info = (usb_disk_info_t *) chan->dev_priv;
611 p_usb_info->DevId = -1;
612 p_usb_info->uPort = -1;
613 p_usb_info->num = -1;
614
615 //diag_printf("Remove USB disk %s\n", szUSBDevName);
616 diag_printf("Remove USB disk %s\n", dev_h->name);
617 chan->callbacks->disk_disconnected(chan);
618
619 if ( _DrvUSB_CBFun != NULL )
620 {
621 if (strlen(dev_h->name) < 12)
622 strcpy(szUSBDevName, dev_h->name);
623 _DrvUSB_CBFun(USB_PLUG_OUT, USB_EVENT_DEV_TYPE_STOR, szUSBDevName);
624 }
625
626 //info->connected = false;
627 //chan->valid = false;
628 }
629
630