platform.c 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554
  1. /*
  2. ** Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/os/linux/platform.c#1
  3. */
  4. /*! \file "platform.c"
  5. \brief This file including the protocol layer privacy function.
  6. This file provided the macros and functions library support for the
  7. protocol layer security setting from wlan_oid.c and for parse.c and
  8. rsn.c and nic_privacy.c
  9. */
  10. /*
  11. ** Log: platform.c
  12. *
  13. * 11 14 2011 cm.chang
  14. * NULL
  15. * Fix compiling warning
  16. *
  17. * 11 10 2011 cp.wu
  18. * [WCXRP00001098] [MT6620 Wi-Fi][Driver] Replace printk by DBG LOG macros in linux porting layer
  19. * 1. eliminaite direct calls to printk in porting layer.
  20. * 2. replaced by DBGLOG, which would be XLOG on ALPS platforms.
  21. *
  22. * 09 13 2011 jeffrey.chang
  23. * [WCXRP00000983] [MT6620][Wi-Fi Driver] invalid pointer casting causes kernel panic during p2p connection
  24. * fix the pointer casting
  25. *
  26. * 06 29 2011 george.huang
  27. * [WCXRP00000818] [MT6620 Wi-Fi][Driver] Remove unused code segment regarding CONFIG_IPV6
  28. * .
  29. *
  30. * 06 28 2011 george.huang
  31. * [WCXRP00000818] [MT6620 Wi-Fi][Driver] Remove unused code segment regarding CONFIG_IPV6
  32. * remove un-used code
  33. *
  34. * 05 11 2011 jeffrey.chang
  35. * NULL
  36. * fix build error
  37. *
  38. * 05 09 2011 jeffrey.chang
  39. * [WCXRP00000710] [MT6620 Wi-Fi] Support pattern filter update function on IP address change
  40. * support ARP filter through kernel notifier
  41. *
  42. * 04 08 2011 pat.lu
  43. * [WCXRP00000623] [MT6620 Wi-Fi][Driver] use ARCH define to distinguish PC Linux driver
  44. * Use CONFIG_X86 instead of PC_LINUX_DRIVER_USE option to have proper compile setting for PC Linux driver
  45. *
  46. * 03 22 2011 pat.lu
  47. * [WCXRP00000592] [MT6620 Wi-Fi][Driver] Support PC Linux Environment Driver Build
  48. * Add a compiler option "PC_LINUX_DRIVER_USE" for building driver in PC Linux environment.
  49. *
  50. * 03 21 2011 cp.wu
  51. * [WCXRP00000540] [MT5931][Driver] Add eHPI8/eHPI16 support to Linux Glue Layer
  52. * improve portability for awareness of early version of linux kernel and wireless extension.
  53. *
  54. * 03 18 2011 jeffrey.chang
  55. * [WCXRP00000512] [MT6620 Wi-Fi][Driver] modify the net device relative functions to support the H/W multiple queue
  56. * remove early suspend functions
  57. *
  58. * 03 03 2011 jeffrey.chang
  59. * NULL
  60. * add the ARP filter callback
  61. *
  62. * 02 15 2011 jeffrey.chang
  63. * NULL
  64. * to support early suspend in android
  65. *
  66. * 02 01 2011 cp.wu
  67. * [WCXRP00000413] [MT6620 Wi-Fi][Driver] Merge 1103 changes on NVRAM file path change to DaVinci main trunk and V1.1
  68. * branch
  69. * upon Jason Zhang(NVRAM owner)'s change, ALPS has modified its NVRAM storage from /nvram/... to /data/nvram/...
  70. *
  71. * 11 01 2010 cp.wu
  72. * [WCXRP00000056] [MT6620 Wi-Fi][Driver] NVRAM implementation with Version Check[WCXRP00000150] [MT6620 Wi-Fi][Driver]
  73. * Add implementation for querying current TX rate from firmware auto rate module
  74. * 1) Query link speed (TX rate) from firmware directly with buffering mechanism to reduce overhead
  75. * 2) Remove CNM CH-RECOVER event handling
  76. * 3) cfg read/write API renamed with kal prefix for unified naming rules.
  77. *
  78. * 10 18 2010 cp.wu
  79. * [WCXRP00000056] [MT6620 Wi-Fi][Driver] NVRAM implementation with Version Check[WCXRP00000086] [MT6620 Wi-Fi][Driver]
  80. * The mac address is all zero at android
  81. * complete implementation of Android NVRAM access
  82. *
  83. * 10 05 2010 cp.wu
  84. * [WCXRP00000056] [MT6620 Wi-Fi][Driver] NVRAM implementation with Version Check
  85. * 1) add NVRAM access API
  86. * 2) fake scanning result when NVRAM doesn't exist and/or version mismatch. (off by compiler option)
  87. * 3) add OID implementation for NVRAM read/write service
  88. *
  89. **
  90. */
  91. /*******************************************************************************
  92. * C O M P I L E R F L A G S
  93. ********************************************************************************
  94. */
  95. /*******************************************************************************
  96. * E X T E R N A L R E F E R E N C E S
  97. ********************************************************************************
  98. */
  99. #include <linux/version.h>
  100. #include <linux/init.h>
  101. #include <linux/types.h>
  102. #include <linux/module.h>
  103. #include <linux/fs.h>
  104. #include <linux/uaccess.h>
  105. #include "gl_os.h"
  106. #ifndef CONFIG_X86
  107. #if defined(CONFIG_HAS_EARLY_SUSPEND)
  108. #include <linux/earlysuspend.h>
  109. #endif
  110. #endif
  111. /*******************************************************************************
  112. * C O N S T A N T S
  113. ********************************************************************************
  114. */
  115. #define WIFI_NVRAM_FILE_NAME "/data/nvram/APCFG/APRDEB/WIFI"
  116. #define WIFI_NVRAM_CUSTOM_NAME "/data/nvram/APCFG/APRDEB/WIFI_CUSTOM"
  117. /*******************************************************************************
  118. * D A T A T Y P E S
  119. ********************************************************************************
  120. */
  121. /*******************************************************************************
  122. * P U B L I C D A T A
  123. ********************************************************************************
  124. */
  125. /*******************************************************************************
  126. * P R I V A T E D A T A
  127. ********************************************************************************
  128. */
  129. /*******************************************************************************
  130. * M A C R O S
  131. ********************************************************************************
  132. */
  133. /*******************************************************************************
  134. * F U N C T I O N D E C L A R A T I O N S
  135. ********************************************************************************
  136. */
  137. /*******************************************************************************
  138. * F U N C T I O N S
  139. ********************************************************************************
  140. */
  141. static int netdev_event(struct notifier_block *nb, unsigned long notification, void *ptr)
  142. {
  143. UINT_8 ip[4] = { 0 };
  144. UINT_32 u4NumIPv4 = 0;
  145. /* #ifdef CONFIG_IPV6 */
  146. #if 0
  147. UINT_8 ip6[16] = { 0 }; /* FIX ME: avoid to allocate large memory in stack */
  148. UINT_32 u4NumIPv6 = 0;
  149. #endif
  150. struct in_ifaddr *ifa = (struct in_ifaddr *)ptr;
  151. struct net_device *prDev = ifa->ifa_dev->dev;
  152. UINT_32 i;
  153. P_PARAM_NETWORK_ADDRESS_IP prParamIpAddr;
  154. P_GLUE_INFO_T prGlueInfo = NULL;
  155. if (prDev == NULL) {
  156. DBGLOG(REQ, ERROR, "netdev_event: device is empty.\n");
  157. return NOTIFY_DONE;
  158. }
  159. DBGLOG(REQ, INFO, "netdev_event, addr=%x, notification=%lx, dev_name=%s\n",
  160. ifa->ifa_address, notification, prDev->name);
  161. if (!fgIsUnderSuspend)
  162. return NOTIFY_DONE;
  163. if ((strncmp(prDev->name, "p2p", 3) != 0) && (strncmp(prDev->name, "wlan", 4) != 0)) {
  164. DBGLOG(REQ, WARN, "netdev_event: not our device\n");
  165. return NOTIFY_DONE;
  166. }
  167. #if 0 /* CFG_SUPPORT_HOTSPOT_2_0 */
  168. {
  169. /* printk(KERN_INFO "[netdev_event] IPV4_DAD is unlock now!!\n"); */
  170. prGlueInfo->fgIsDad = FALSE;
  171. }
  172. #endif
  173. prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prDev));
  174. if (prGlueInfo == NULL) {
  175. DBGLOG(REQ, ERROR, "netdev_event: prGlueInfo is empty.\n");
  176. return NOTIFY_DONE;
  177. }
  178. ASSERT(prGlueInfo);
  179. /* <3> get the IPv4 address */
  180. if (!prDev || !(prDev->ip_ptr) ||
  181. !((struct in_device *)(prDev->ip_ptr))->ifa_list ||
  182. !(&(((struct in_device *)(prDev->ip_ptr))->ifa_list->ifa_local))) {
  183. DBGLOG(REQ, INFO, "ip is not available.\n");
  184. return NOTIFY_DONE;
  185. }
  186. kalMemCopy(ip, &(((struct in_device *)(prDev->ip_ptr))->ifa_list->ifa_local), sizeof(ip));
  187. DBGLOG(REQ, INFO, "ip is %d.%d.%d.%d\n", ip[0], ip[1], ip[2], ip[3]);
  188. /* todo: traverse between list to find whole sets of IPv4 addresses */
  189. if (!((ip[0] == 0) && (ip[1] == 0) && (ip[2] == 0) && (ip[3] == 0)))
  190. u4NumIPv4++;
  191. /* #ifdef CONFIG_IPV6 */
  192. #if 0
  193. if (!prDev || !(prDev->ip6_ptr) ||
  194. !((struct in_device *)(prDev->ip6_ptr))->ifa_list ||
  195. !(&(((struct in_device *)(prDev->ip6_ptr))->ifa_list->ifa_local))) {
  196. DBGLOG(REQ, INFO, "ipv6 is not available.\n");
  197. return NOTIFY_DONE;
  198. }
  199. kalMemCopy(ip6, &(((struct in_device *)(prDev->ip6_ptr))->ifa_list->ifa_local), sizeof(ip6));
  200. DBGLOG(REQ, INFO, "ipv6 is %d.%d.%d.%d.%d.%d.%d.%d.%d.%d.%d.%d.%d.%d.%d.%d\n",
  201. ip6[0], ip6[1], ip6[2], ip6[3],
  202. ip6[4], ip6[5], ip6[6], ip6[7], ip6[8], ip6[9], ip6[10], ip6[11], ip6[12], ip6[13], ip6[14], ip6[15]);
  203. /* todo: traverse between list to find whole sets of IPv6 addresses */
  204. if (!((ip6[0] == 0) && (ip6[1] == 0) && (ip6[2] == 0) && (ip6[3] == 0) && (ip6[4] == 0) && (ip6[5] == 0)))
  205. /* u4NumIPv6++; */
  206. #endif
  207. /* here we can compare the dev with other network's netdev to */
  208. /* set the proper arp filter */
  209. /* */
  210. /* IMPORTANT: please make sure if the context can sleep, if the context can't sleep */
  211. /* we should schedule a kernel thread to do this for us */
  212. /* <7> set up the ARP filter */
  213. {
  214. WLAN_STATUS rStatus = WLAN_STATUS_FAILURE;
  215. UINT_32 u4SetInfoLen = 0;
  216. UINT_8 aucBuf[32] = { 0 };
  217. UINT_32 u4Len = OFFSET_OF(PARAM_NETWORK_ADDRESS_LIST, arAddress);
  218. P_PARAM_NETWORK_ADDRESS_LIST prParamNetAddrList = (P_PARAM_NETWORK_ADDRESS_LIST) aucBuf;
  219. P_PARAM_NETWORK_ADDRESS prParamNetAddr = prParamNetAddrList->arAddress;
  220. /* #ifdef CONFIG_IPV6 */
  221. #if 0
  222. prParamNetAddrList->u4AddressCount = u4NumIPv4 + u4NumIPv6;
  223. #else
  224. prParamNetAddrList->u4AddressCount = u4NumIPv4;
  225. #endif
  226. prParamNetAddrList->u2AddressType = PARAM_PROTOCOL_ID_TCP_IP;
  227. for (i = 0; i < u4NumIPv4; i++) {
  228. prParamNetAddr->u2AddressLength = sizeof(PARAM_NETWORK_ADDRESS_IP); /* 4;; */
  229. prParamNetAddr->u2AddressType = PARAM_PROTOCOL_ID_TCP_IP;
  230. #if 0
  231. kalMemCopy(prParamNetAddr->aucAddress, ip, sizeof(ip));
  232. prParamNetAddr = (P_PARAM_NETWORK_ADDRESS) ((PUINT_8) prParamNetAddr + sizeof(ip));
  233. u4Len += OFFSET_OF(PARAM_NETWORK_ADDRESS, aucAddress) + sizeof(ip);
  234. #else
  235. prParamIpAddr = (P_PARAM_NETWORK_ADDRESS_IP) prParamNetAddr->aucAddress;
  236. kalMemCopy(&prParamIpAddr->in_addr, ip, sizeof(ip));
  237. prParamNetAddr =
  238. (P_PARAM_NETWORK_ADDRESS) ((PUINT_8) prParamNetAddr + sizeof(PARAM_NETWORK_ADDRESS));
  239. u4Len += OFFSET_OF(PARAM_NETWORK_ADDRESS, aucAddress) + sizeof(PARAM_NETWORK_ADDRESS);
  240. #endif
  241. }
  242. /* #ifdef CONFIG_IPV6 */
  243. #if 0
  244. for (i = 0; i < u4NumIPv6; i++) {
  245. prParamNetAddr->u2AddressLength = 6;
  246. prParamNetAddr->u2AddressType = PARAM_PROTOCOL_ID_TCP_IP;
  247. kalMemCopy(prParamNetAddr->aucAddress, ip6, sizeof(ip6));
  248. prParamNetAddr = (P_PARAM_NETWORK_ADDRESS) ((PUINT_8) prParamNetAddr + sizeof(ip6));
  249. u4Len += OFFSET_OF(PARAM_NETWORK_ADDRESS, aucAddress) + sizeof(ip6);
  250. }
  251. #endif
  252. ASSERT(u4Len <= sizeof(aucBuf));
  253. DBGLOG(REQ, INFO, "kalIoctl (0x%p, 0x%p)\n", prGlueInfo, prParamNetAddrList);
  254. rStatus = kalIoctl(prGlueInfo,
  255. wlanoidSetNetworkAddress,
  256. (PVOID) prParamNetAddrList, u4Len, FALSE, FALSE, TRUE, FALSE, &u4SetInfoLen);
  257. if (rStatus != WLAN_STATUS_SUCCESS)
  258. DBGLOG(REQ, ERROR, "set HW pattern filter fail 0x%x\n", rStatus);
  259. }
  260. return NOTIFY_DONE;
  261. }
  262. /* #if CFG_SUPPORT_HOTSPOT_2_0 */
  263. #if 0
  264. static int net6dev_event(struct notifier_block *nb, unsigned long notification, void *ptr)
  265. {
  266. struct inet6_ifaddr *ifa = (struct inet6_ifaddr *)ptr;
  267. struct net_device *prDev = ifa->idev->dev;
  268. P_GLUE_INFO_T prGlueInfo = NULL;
  269. if (prDev == NULL) {
  270. DBGLOG(REQ, INFO, "net6dev_event: device is empty.\n");
  271. return NOTIFY_DONE;
  272. }
  273. if ((strncmp(prDev->name, "p2p", 3) != 0) && (strncmp(prDev->name, "wlan", 4) != 0)) {
  274. DBGLOG(REQ, INFO, "net6dev_event: xxx\n");
  275. return NOTIFY_DONE;
  276. }
  277. if (strncmp(prDev->name, "p2p", 3) == 0) {
  278. /* because we store the address of prGlueInfo in p2p's private date of net device */
  279. /* *((P_GLUE_INFO_T *) netdev_priv(prGlueInfo->prP2PInfo->prDevHandler)) = prGlueInfo; */
  280. prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prDev));
  281. } else { /* wlan0 */
  282. prGlueInfo = (P_GLUE_INFO_T) netdev_priv(prDev);
  283. }
  284. if (prGlueInfo == NULL) {
  285. DBGLOG(REQ, INFO, "netdev_event: prGlueInfo is empty.\n");
  286. return NOTIFY_DONE;
  287. }
  288. /* printk(KERN_INFO "[net6dev_event] IPV6_DAD is unlock now!!\n"); */
  289. prGlueInfo->fgIs6Dad = FALSE;
  290. return NOTIFY_DONE;
  291. }
  292. #endif
  293. static struct notifier_block inetaddr_notifier = {
  294. .notifier_call = netdev_event,
  295. };
  296. #if 0 /* CFG_SUPPORT_HOTSPOT_2_0 */
  297. static struct notifier_block inet6addr_notifier = {
  298. .notifier_call = net6dev_event,
  299. };
  300. #endif
  301. void wlanRegisterNotifier(void)
  302. {
  303. register_inetaddr_notifier(&inetaddr_notifier);
  304. #if CFG_SUPPORT_HOTSPOT_2_0
  305. /* register_inet6addr_notifier(&inet6addr_notifier); */
  306. #endif
  307. }
  308. /* EXPORT_SYMBOL(wlanRegisterNotifier); */
  309. void wlanUnregisterNotifier(void)
  310. {
  311. unregister_inetaddr_notifier(&inetaddr_notifier);
  312. #if CFG_SUPPORT_HOTSPOT_2_0
  313. /* unregister_inetaddr_notifier(&inet6addr_notifier); */
  314. #endif
  315. }
  316. /* EXPORT_SYMBOL(wlanUnregisterNotifier); */
  317. /*----------------------------------------------------------------------------*/
  318. /*!
  319. * \brief Utility function for reading data from files on NVRAM-FS
  320. *
  321. * \param[in]
  322. * filename
  323. * len
  324. * offset
  325. * \param[out]
  326. * buf
  327. * \return
  328. * actual length of data being read
  329. */
  330. /*----------------------------------------------------------------------------*/
  331. static int nvram_read(char *filename, char *buf, ssize_t len, int offset)
  332. {
  333. #if CFG_SUPPORT_NVRAM
  334. struct file *fd;
  335. int retLen = -1;
  336. mm_segment_t old_fs = get_fs();
  337. set_fs(KERNEL_DS);
  338. fd = filp_open(filename, O_RDONLY, 0644);
  339. if (IS_ERR(fd)) {
  340. DBGLOG(INIT, INFO, "[MT6620][nvram_read] : failed to open!!\n");
  341. return -1;
  342. }
  343. do {
  344. if ((fd->f_op == NULL) || (fd->f_op->read == NULL)) {
  345. DBGLOG(INIT, INFO, "[MT6620][nvram_read] : file can not be read!!\n");
  346. break;
  347. }
  348. if (fd->f_pos != offset) {
  349. if (fd->f_op->llseek) {
  350. if (fd->f_op->llseek(fd, offset, 0) != offset) {
  351. DBGLOG(INIT, INFO, "[MT6620][nvram_read] : failed to seek!!\n");
  352. break;
  353. }
  354. } else {
  355. fd->f_pos = offset;
  356. }
  357. }
  358. retLen = fd->f_op->read(fd, buf, len, &fd->f_pos);
  359. } while (FALSE);
  360. filp_close(fd, NULL);
  361. set_fs(old_fs);
  362. return retLen;
  363. #else /* !CFG_SUPPORT_NVRAM */
  364. return -EIO;
  365. #endif
  366. }
  367. /*----------------------------------------------------------------------------*/
  368. /*!
  369. * \brief Utility function for writing data to files on NVRAM-FS
  370. *
  371. * \param[in]
  372. * filename
  373. * buf
  374. * len
  375. * offset
  376. * \return
  377. * actual length of data being written
  378. */
  379. /*----------------------------------------------------------------------------*/
  380. static int nvram_write(char *filename, char *buf, ssize_t len, int offset)
  381. {
  382. #if CFG_SUPPORT_NVRAM
  383. struct file *fd;
  384. int retLen = -1;
  385. mm_segment_t old_fs = get_fs();
  386. set_fs(KERNEL_DS);
  387. fd = filp_open(filename, O_WRONLY | O_CREAT, 0644);
  388. if (IS_ERR(fd)) {
  389. DBGLOG(INIT, INFO, "[MT6620][nvram_write] : failed to open!!\n");
  390. return -1;
  391. }
  392. do {
  393. if ((fd->f_op == NULL) || (fd->f_op->write == NULL)) {
  394. DBGLOG(INIT, INFO, "[MT6620][nvram_write] : file can not be write!!\n");
  395. break;
  396. }
  397. /* End of if */
  398. if (fd->f_pos != offset) {
  399. if (fd->f_op->llseek) {
  400. if (fd->f_op->llseek(fd, offset, 0) != offset) {
  401. DBGLOG(INIT, INFO, "[MT6620][nvram_write] : failed to seek!!\n");
  402. break;
  403. }
  404. } else {
  405. fd->f_pos = offset;
  406. }
  407. }
  408. retLen = fd->f_op->write(fd, buf, len, &fd->f_pos);
  409. } while (FALSE);
  410. filp_close(fd, NULL);
  411. set_fs(old_fs);
  412. return retLen;
  413. #else /* !CFG_SUPPORT_NVRAMS */
  414. return -EIO;
  415. #endif
  416. }
  417. /*----------------------------------------------------------------------------*/
  418. /*!
  419. * \brief API for reading data on NVRAM
  420. *
  421. * \param[in]
  422. * prGlueInfo
  423. * u4Offset
  424. * \param[out]
  425. * pu2Data
  426. * \return
  427. * TRUE
  428. * FALSE
  429. */
  430. /*----------------------------------------------------------------------------*/
  431. BOOLEAN kalCfgDataRead16(IN P_GLUE_INFO_T prGlueInfo, IN UINT_32 u4Offset, OUT PUINT_16 pu2Data)
  432. {
  433. if (pu2Data == NULL)
  434. return FALSE;
  435. if (nvram_read(WIFI_NVRAM_FILE_NAME,
  436. (char *)pu2Data, sizeof(unsigned short), u4Offset) != sizeof(unsigned short)) {
  437. return FALSE;
  438. } else {
  439. return TRUE;
  440. }
  441. }
  442. /*----------------------------------------------------------------------------*/
  443. /*!
  444. * \brief API for writing data on NVRAM
  445. *
  446. * \param[in]
  447. * prGlueInfo
  448. * u4Offset
  449. * u2Data
  450. * \return
  451. * TRUE
  452. * FALSE
  453. */
  454. /*----------------------------------------------------------------------------*/
  455. BOOLEAN kalCfgDataWrite16(IN P_GLUE_INFO_T prGlueInfo, UINT_32 u4Offset, UINT_16 u2Data)
  456. {
  457. if (nvram_write(WIFI_NVRAM_FILE_NAME,
  458. (char *)&u2Data, sizeof(unsigned short), u4Offset) != sizeof(unsigned short)) {
  459. return FALSE;
  460. } else {
  461. return TRUE;
  462. }
  463. }
  464. BOOLEAN kalCfgDataRead(IN P_GLUE_INFO_T prGlueInfo, IN UINT_32 u4Offset,
  465. IN UINT_32 u4Len, OUT PUINT_16 pu2Data)
  466. {
  467. if (pu2Data == NULL)
  468. return FALSE;
  469. if (nvram_read(WIFI_NVRAM_FILE_NAME,
  470. (char *)pu2Data, u4Len, u4Offset) != u4Len) {
  471. return FALSE;
  472. } else {
  473. return TRUE;
  474. }
  475. }