音影先锋亚洲天堂网|电影世界尽头的爱完整版播放|国产 熟女 91|高清无码免费观看欧美日韩|韩国一区二区三区黄色录像|美女亚洲加勒比在线|亚洲综合网 开心五月|7x成人在线入口|成人网站免费日韩毛片区|国产黄片?一级?二级?三级

編寫Windows CE.net的usb驅(qū)動(dòng)程序教程

出處:互聯(lián)網(wǎng)    發(fā)布于:2011-09-03 08:12:23

  Windows CE.NET 是微軟推出的功能強(qiáng)大的嵌入式操作系統(tǒng),國內(nèi)采用此操作系統(tǒng)的廠商已經(jīng)很多了,本文就以windows ce.net為例,簡單介紹一下如何開發(fā)windows ce.net下的USB驅(qū)動(dòng)程序。
  Windows CE.NET 的USB系統(tǒng)軟件分為兩層: USB Client設(shè)備驅(qū)動(dòng)程序和底層的Windows CE實(shí)現(xiàn)的函數(shù)層。USB設(shè)備驅(qū)動(dòng)程序主要負(fù)責(zé)利用系統(tǒng)提供的底層接口配置設(shè)備,和設(shè)備進(jìn)行通訊。底層的函數(shù)提本身又由兩部分組成,通用串行總線驅(qū)動(dòng)程序(USBD)模塊和較低的主控制器驅(qū)動(dòng)程序(HCD)模塊。HCD負(fù)責(zé)層的處理,USBD模塊實(shí)現(xiàn)較高的USBD函數(shù)接口。USB設(shè)備驅(qū)動(dòng)主要利用 USBD接口函數(shù)和他們的外圍設(shè)備打交道。
  USB設(shè)備驅(qū)動(dòng)程序主要和USBD打交道,所以我們必須詳細(xì)的了解USBD提供的函數(shù)。

  主要的傳輸函數(shù)有:
  abourttransferissuecontroltransfer
  closetransfer issueinterruptransfer
  getisochresultissueisochtransfer
  gettransferstatus istransfercomplete
  issuebulktransfer issuevendortransfer
  

    主要的用于打開和關(guān)閉usbd和usb設(shè)備之間的通信通道的函數(shù)有:
    abortpipetransfersclosepipe
    isdefaultpipehalted ispipehalted 
    openpiperesetdefaultpipe
    resetpipe

  相應(yīng)的打包函數(shù)接口有:
  getframelengthgetframenumberreleaseframelengthcontrol
  setframelengthtakeframelengthcontrol

  取得設(shè)置設(shè)備配置函數(shù):
  clearfeature setdescriptor
  getdescriptorsetfeature
  getinterface setinterface
  getstatussyncframe

  與usb進(jìn)行交互的實(shí)現(xiàn)方法相關(guān)的多任務(wù)函數(shù):
  findinterfaceregisterclientdeviceid
  getdeviceinforegisterclientsettings
  getusbdversion registernotificationroutine
  loadgenericinterfacedriver translatestringdescr
  openclientregisterkeyunregisternotificationroutine


  常見的Windows CE.NET下USB的設(shè)備驅(qū)動(dòng)程序的編寫有以下幾種方法:
  ● 流式接口函數(shù)這種驅(qū)動(dòng)程序主要呈現(xiàn)流式函數(shù)接口,主要輸出XXX_Init,XXX_Deinit,XXX_Open,XXX_Close,XXX_Open,XXX_Close,XXX_Read,XXX_Write,XXX_Seek, XXX_IOControl,XXX_PowerUp,XXX_PowerDown等流式接口,注意上述的幾個(gè)接口一定都要輸出,另外XXX必須為三個(gè)字符,否則會(huì)出錯(cuò)。但是此類的驅(qū)動(dòng)程序不是通過設(shè)備管理接口來加載的,所以必須手工的調(diào)用RegisterDevice()和 DeregisterDevice()函數(shù)來加載和卸載驅(qū)動(dòng)程序。用戶可以將此類的設(shè)備作為標(biāo)準(zhǔn)的文件來操作,只要調(diào)用相應(yīng)的文件操作就可以和驅(qū)動(dòng)程序打交道。
  ● 使用現(xiàn)有的Window CE.NET的應(yīng)用程序接口此類設(shè)備主要是利用Windows CE.NET中已經(jīng)有了現(xiàn)成的函數(shù)接口,例如USB Mass Storage Disk,它主要利用現(xiàn)有的Windows CE.Net中已經(jīng)有的可安裝文件系統(tǒng)接口,呈現(xiàn)給系統(tǒng)可用的文件系統(tǒng),對于用戶來講,它是透明的,用戶僅僅感覺在操作一個(gè)文件夾。
  ● 創(chuàng)建指定到特定的USBD的用戶指定的API這種方法在USBD呈現(xiàn)設(shè)備時(shí)不需要任何限制,主要是特制的提供API給用戶,一般不太常見。
  USB設(shè)備驅(qū)動(dòng)程序必須輸出的函數(shù)有:
  ● USBDeviecAttach當(dāng)USB設(shè)備連接到計(jì)算機(jī)上時(shí),USBD模塊就會(huì)調(diào)用此函數(shù),這個(gè)函數(shù)主要用于初始化USB設(shè)備,取得USB設(shè)備信息,配置USB設(shè)備,并且申請必需的資源。
  ● USBInstallDriver主要用于創(chuàng)建一個(gè)驅(qū)動(dòng)程序加載所需的注冊表信息,例如讀寫超時(shí),設(shè)備名稱等。
  ● USBUninstallDriver主要用于釋放驅(qū)動(dòng)程序所占用的資源,以及刪除USBInstallDriver函數(shù)創(chuàng)建的注冊表等。
  上述的三個(gè)函數(shù)接口是所有的USB驅(qū)動(dòng)程序必須提供的,缺一不可。
  另外比較重要的是USB設(shè)備驅(qū)動(dòng)程序的注冊表配置,一般的USB設(shè)備驅(qū)動(dòng)程序的注冊表配置HKEY_LOCAL_MACHINE\Drivers\USB \LoadClients下,每個(gè)驅(qū)動(dòng)程序的子鍵都有Group1_ID\Group2_ID\Group3_ID\DriverName格式,如果注冊表信息與USB設(shè)備信息符合,USBD就會(huì)加載此驅(qū)動(dòng)程序。否則設(shè)備的子鍵應(yīng)該由供應(yīng)商,設(shè)備類和協(xié)議信息通過下劃線組成。
  例如你有個(gè)PDA設(shè)備,它具有一個(gè)USB接口,它的供應(yīng)廠商ID假設(shè)為0x0888,設(shè)備ID為0x0999,沒有使用特殊的協(xié)議,那么它的加載注冊表應(yīng)該寫為:
  [HKEY_LOCAL_MACHINE\Drivers\USB\LoadClients\2184_2457\Default\Default\PDA] "DLL"="pdausb.dll"需要注意的是注冊表構(gòu)成都是十進(jìn)制數(shù)值來標(biāo)識的,注意一下十進(jìn)制和十六進(jìn)制的轉(zhuǎn)換。
  有了這些基本信息,就可以編寫USB設(shè)備了。
  首先,必須輸出USBD要求調(diào)用的三個(gè)函數(shù),首先到設(shè)備插入到USB端口時(shí),USBD會(huì)調(diào)用USBDeviceAttach()函數(shù),相應(yīng)的代碼如下:

  extern c bool
  usbdeviceattach(
  usb_handle hdevice, // usb設(shè)備句柄
  lpcusb_funcs lpusbfuncs, // usbdi的函數(shù)集合
  lpcusb_interface lpinterface, // 設(shè)備接口描述信息
  lpcwstr szuniquedriverid, // 設(shè)備id描述字符串。
  lpbool facceptcontrol, // 返回true,標(biāo)識我們可以控制此設(shè)備, 反之表示不能控制
  dword dwunused)
  {
  *facceptcontrol = false;
  // 我們的鼠標(biāo)設(shè)備有特定的描述信息,要檢測是否是我們的設(shè)備。
  if (lpinterface == null)
  return false;
  // 打印相關(guān)的usb設(shè)備接口描述信息。
  debugmsg(zone_init,(text(usbmouse: deviceattach, if %u, #ep:%u, class:%u, sub:%u,prot:%urn), lpinterface->descriptor.binterfacenumber,lpinterface->descriptor.bnumendpoints, lpinterface->descriptor.binterfaceclass,lpinterface->descriptor.binterfacesubclass,lpinterface->descriptor.binterfaceprotocol));
  // 初試數(shù)據(jù)usb鼠標(biāo)類,產(chǎn)生一個(gè)接受usb鼠標(biāo)數(shù)據(jù)的線程
  cmouse * pmouse = new cmouse(hdevice, lpusbfuncs, lpinterface);
  if (pmouse == null)
  return false;
  if (!pmouse->initialize())
  {
  delete pmouse;
  return false;
  }

  // 注冊一個(gè)監(jiān)控usb設(shè)備事件的回調(diào)函數(shù),用于監(jiān)控usb設(shè)備是否已經(jīng)拔掉。
 ?。?lpusbfuncs->lpregisternotificationroutine)(hdevice,
  usbdevicenotifications, pmouse);
  *facceptcontrol = true;
  return true;
  }
  第二個(gè)函數(shù)是 usbinstalldriver()函數(shù),
  一些基本定義如下:
  const wchar gcszregisterclientdriverid[] = lregisterclientdriverid;
  const wchar gcszregisterclientsettings[] = lregisterclientsettings;
  const wchar gcszunregisterclientdriverid[] = lunregisterclientdriverid;
  const wchar gcszunregisterclientsettings[] = lunregisterclientsettings;
  const wchar gcszmousedriverid[] = lgeneric_sample_mouse_driver;
  函數(shù)接口如下:
  extern c bool
  usbinstalldriver(
  lpcwstr szdriverlibfile) // @parm [in] - contains client driver dll name
  {
  bool fret = false;
  hinstance hinst = loadlibrary(lusbd.dll);
  // 注冊usb設(shè)備信息
  if(hinst)
  {
  lpregister_client_driver_id pregisterid = (lpregister_client_driver_id)
  getprocaddress(hinst, gcszregisterclientdriverid);
  lpregister_client_settings pregistersettings =
 ?。╨pregister_client_settings) getprocaddress(hinst,
  gcszregisterclientsettings);
  if(pregisterid && pregistersettings)
  {
  usb_driver_settings driversettings;
  driversettings.dwcount = sizeof(driversettings);
  // 設(shè)置我們的特定的信息。
  driversettings.dwvendorid = usb_no_info;
  driversettings.dwproductid = usb_no_info;
  driversettings.dwreleasenumber = usb_no_info;
  driversettings.dwdeviceclass = usb_no_info;
  driversettings.dwdevicesubclass = usb_no_info;
  driversettings.dwdeviceprotocol = usb_no_info;
  driversettings.dwinterfaceclass = 0x03; // hid
  driversettings.dwinterfacesubclass = 0x01; // boot device
  driversettings.dwinterfaceprotocol = 0x02; // mouse
  fret = (*pregisterid)(gcszmousedriverid);
  if(fret)
  {
  fret = (*pregistersettings)(szdriverlibfile,
  gcszmousedriverid, null, &driversettings);
  if(!fret)
  {
  //bugbug unregister the client drivers id
  }
  }
  }
  else
  {
  retailmsg(1,(text(!usbmouse: error getting usbd function pointersrn)));
  }
  freelibrary(hinst);
  }
  return fret;
  }

  上述代碼主要用于產(chǎn)生USB設(shè)備驅(qū)動(dòng)程序需要的注冊表信息,要注意的是:USB設(shè)備驅(qū)動(dòng)程序不使用標(biāo)準(zhǔn)的注冊表函數(shù),而是使用RegisterClientDriverID()與RegisterClientSettings來注冊相應(yīng)的設(shè)備信息。
  另外一個(gè)函數(shù)是usbuninstalldriver()函數(shù),具體代碼如下:
  extern c bool
  usbuninstalldriver()
  {
  bool fret = false;
  hinstance hinst = loadlibrary(lusbd.dll);
  if(hinst)
  {
  lpun_register_client_driver_id punregisterid =
 ?。╨pun_register_client_driver_id)
  getprocaddress(hinst, gcszunregisterclientdriverid);
  lpun_register_client_settings punregistersettings =
 ?。╨pun_register_client_settings) getprocaddress(hinst,
  gcszunregisterclientsettings);
  if(punregistersettings)
  {
  usb_driver_settings driversettings;
  driversettings.dwcount = sizeof(driversettings);
  // 必須填入與注冊時(shí)相同的信息。
  driversettings.dwvendorid = usb_no_info;
  driversettings.dwproductid = usb_no_info;
  driversettings.dwreleasenumber = usb_no_info;
  driversettings.dwdeviceclass = usb_no_info;
  driversettings.dwdevicesubclass = usb_no_info;
  driversettings.dwdeviceprotocol = usb_no_info;
  driversettings.dwinterfaceclass = 0x03; // hid
  driversettings.dwinterfacesubclass = 0x01; // boot device
  driversettings.dwinterfaceprotocol = 0x02; // mouse
  fret = (*punregistersettings)(gcszmousedriverid, null,
 ?。riversettings);
  }
  if(punregisterid)
  {
  bool frettemp = (*punregisterid)(gcszmousedriverid);
  fret = fret ? frettemp : fret;
  }
  freelibrary(hinst);
  }
  return fret;
  }

  此函數(shù)主要用于刪除USBInstallDriver()時(shí)創(chuàng)建的注冊表信息,同樣的它使用自己的函數(shù)接口UnRegisterClientDriverID()和UnRegisterClientSettings()來做相應(yīng)的處理。


    另外一個(gè)需要處理的注冊的監(jiān)控通知函數(shù)usbdevicenotifications():
  extern c bool usbdevicenotifications(lpvoid lpvnotifyparameter, dword dwcode,
  lpdword * dwinfo1, lpdword * dwinfo2, lpdword * dwinfo3,
  lpdword * dwinfo4)
  {
  cmouse * pmouse = (cmouse *)lpvnotifyparameter;
  switch(dwcode)
  {
  case usb_close_device:
  //刪除相關(guān)的資源。
  delete pmouse;
  return true;
  }
  return false;
  }
  usb鼠標(biāo)的類的定義如下:
  class cmouse
  {
  public:
  cmouse::cmouse(usb_handle hdevice, lpcusb_funcs lpusbfuncs,
  lpcusb_interface lpinterface);
  ~cmouse();
  bool initialize();
  private:
  // 傳輸完畢調(diào)用的回調(diào)函數(shù)
  static dword callback mousetransfercompletestub(lpvoid lpvnotifyparameter);
  // 中斷處理函數(shù)
  static ulong callback cmouse::mousethreadstub(pvoid context);
  dword mousetransfercomplete();
  dword mousethread();
  bool submitinterrupt();
  bool handleinterrupt();
  bool m_fclosing;
  bool m_freadyformouseevents;
  handle m_hevent;
  handle m_hthread;
  usb_handle m_hdevice;
  usb_pipe m_hinterruptpipe;
  usb_transfer m_hinterrupttransfer;
  lpcusb_funcs m_lpusbfuncs;
  lpcusb_interface m_pinterface;
  bool m_fprevbutton1;
  bool m_fprevbutton2;
  bool m_fprevbutton3;
  // 數(shù)據(jù)接受緩沖區(qū)。
  byte m_pbdatabuffer[8];
  };
  具體實(shí)現(xiàn)如下:
  // 構(gòu)造函數(shù),初始化時(shí)調(diào)用
  cmouse::cmouse(usb_handle hdevice, lpcusb_funcs lpusbfuncs,
  lpcusb_interface lpinterface)
  {
  m_fclosing = false;
  m_freadyformouseevents = false;
  m_hevent = null;
  m_hthread = null;
  m_hdevice = hdevice;
  m_hinterruptpipe = null;
  m_hinterrupttransfer = null;
  m_lpusbfuncs = lpusbfuncs;
  m_pinterface = lpinterface;
  m_fprevbutton1 = false;
  m_fprevbutton2 = false;
  m_fprevbutton3 = false;
  memset(m_pbdatabuffer, 0, sizeof(m_pbdatabuffer));
  }
  // 析構(gòu)函數(shù),用于清除申請的資源。
  cmouse::~cmouse()
  {
  // 通知系統(tǒng)去關(guān)閉相關(guān)的函數(shù)接口。
  m_fclosing = true;
  // wake up the connection thread again and give it time to die.
  if (m_hevent != null)
  {
  // 通知關(guān)閉數(shù)據(jù)接受線程。
  setevent(m_hevent);
  if (m_hthread != null)
  {
  dword dwwaitreturn;
  dwwaitreturn = waitforsingleobject(m_hthread, 1000);
  if (dwwaitreturn != wait_object_0)
  {
  terminatethread(m_hthread, dword(-1));
  }
  closehandle(m_hthread);
  m_hthread = null;
  }
  closehandle(m_hevent);
  m_hevent = null;
  }
  if(m_hinterrupttransfer)
 ?。?m_lpusbfuncs->lpclosetransfer)(m_hinterrupttransfer);
  if(m_hinterruptpipe)
 ?。?m_lpusbfuncs->lpclosepipe)(m_hinterruptpipe);
  }
  // 初始化usb鼠標(biāo)驅(qū)動(dòng)程序
  bool cmouse::initialize()
  {
  lpcusb_device lpdeviceinfo = (*m_lpusbfuncs->lpgetdeviceinfo)(m_hdevice);
  // 檢測配置:usb鼠標(biāo)應(yīng)該只有一個(gè)中斷管道
  if ((m_pinterface->lpendpoints[0].descriptor.bmattributes & usb_endpoint_type_mask) != usb_endpoint_type_interrupt)
  {
  retailmsg(1,(text(!usbmouse: ep 0 wrong type (%u)!rn),
  m_pinterface->lpendpoints[0].descriptor.bmattributes));
  return false;
  }
  debugmsg(zone_init,(text(usbmouse: ep 0:maxpacket: %u, interval: %urn),
  m_pinterface->lpendpoints[0].descriptor.wmaxpacketsize,
  m_pinterface->lpendpoints[0].descriptor.binterval));
  m_hinterruptpipe = (*m_lpusbfuncs->lpopenpipe)(m_hdevice,
 ?。_pinterface->lpendpoints[0].descriptor);
  if (m_hinterruptpipe == null) {
  retailmsg(1,(text(mouse: error opening interrupt pipern)));
  return (false);
  }
  m_hevent = createevent(null, false, false, null);
  if (m_hevent == null)
  {
  retailmsg(1,(text(usbmouse: error on createevent for connect eventrn)));
  return(false);
  }
  // 創(chuàng)建數(shù)據(jù)接受線程
  m_hthread = createthread(0, 0, mousethreadstub, this, 0, null);
  if (m_hthread == null)
  {
  retailmsg(1,(text(usbmouse: error on createthreadrn)));
  return(false);
  }
  return(true);
  }
  // 從usb鼠標(biāo)設(shè)備中讀出數(shù)據(jù),產(chǎn)生相應(yīng)的鼠標(biāo)事件。
  bool cmouse::submitinterrupt()
  {
  if(m_hinterrupttransfer)
 ?。?m_lpusbfuncs->lpclosetransfer)(m_hinterrupttransfer);
  // 從usb鼠標(biāo)pipe中讀數(shù)據(jù)
  m_hinterrupttransfer = (*m_lpusbfuncs->lpissueinterrupttransfer)
 ?。╩_hinterruptpipe, mousetransfercompletestub, this,
  usb_in_transfer | usb_short_transfer_ok, // 表示讀數(shù)據(jù)
  min(m_pinterface->lpendpoints[0].descriptor.wmaxpacketsize,
  sizeof(m_pbdatabuffer)),
  m_pbdatabuffer,
  null);
  if (m_hinterrupttransfer == null)
  {
  debugmsg(zone_error,(l !usbmouse: error in issueinterrupttransferrn));
  return false;
  }
  else
  {
  debugmsg(zone_transfer,(lusbmouse::submitinterrupt,transfer:0x%xrn,
  m_hinterrupttransfer));
  }
  return true;
  }
  // 處理鼠標(biāo)中斷傳輸?shù)臄?shù)據(jù)
  bool cmouse::handleinterrupt()
  {
  dword dwerror;
  dword dwbytes;
  dword dwflags = 0;
  int dx = (signed char)m_pbdatabuffer[1];
  int dy = (signed char)m_pbdatabuffer[2];
  bool fbutton1 = m_pbdatabuffer[0] & 0x01 ? true : false;
  bool fbutton2 = m_pbdatabuffer[0] & 0x02 ? true : false;
  bool fbutton3 = m_pbdatabuffer[0] & 0x04 ? true : false;
  if (?。?m_lpusbfuncs->lpgettransferstatus)(m_hinterrupttransfer, &dwbytes,&dwerror))
  {
  debugmsg(zone_error,(text(!usbmouse: error in gettransferstatus(0x%x)rn),
  m_hinterrupttransfer));
  return false;
  }
  else
  {
  debugmsg(zone_transfer,(text(usbmouse::handleinterrupt, htransfer 0x%x complete (%u bytes, error:%x)rn),
  m_hinterrupttransfer,dwbytes,dwerror));
  }
  if (!submitinterrupt())
  return false;
  if(dwerror != usb_no_error)
  {
  debugmsg(zone_error,(text(!usbmouse: error 0x%x in interrupt transferrn),dwerror));
  return true;
  }
  if(dwbytes < 3)
  {
  debugmsg(zone_error,(text(!usbmouse: invalid byte cnt %u from interrupt transferrn),dwbytes));
  return true;
  }
  if(dx || dy)
  dwflags |= mouseeventf_move;
  if(fbutton1 != m_fprevbutton1)
  {
  if(fbutton1)
  dwflags |= mouseeventf_leftdown;
  else
  dwflags |= mouseeventf_leftup;
  }
  if(fbutton2 != m_fprevbutton2)
  {
  if(fbutton2)
  dwflags |= mouseeventf_rightdown;
  else
  dwflags |= mouseeventf_rightup;
  }
  if(fbutton3 != m_fprevbutton3)
  {
  if(fbutton3)
  dwflags |= mouseeventf_middledown;
  else
  dwflags |= mouseeventf_middleup;
  }
  m_fprevbutton1 = fbutton1;
  m_fprevbutton2 = fbutton2;
  m_fprevbutton3 = fbutton3;
  debugmsg(zone_events,
 ?。╰ext(usbmouse event: dx:%d, dy:%d, dwflags:0x%x (b1:%u, b2:%u, b3:%u)rn),
  dx,dy,dwflags,fbutton1,fbutton2,fbutton3));
  // 通知系統(tǒng)產(chǎn)生鼠標(biāo)事件
  if (m_freadyformouseevents)
  mouse_event(dwflags, dx, dy, 0, 0);
  else
  m_freadyformouseevents = isapiready(sh_wmgr);
  return true;
  }
  dword callback cmouse::mousetransfercompletestub(lpvoid lpvnotifyparameter)
  {
  cmouse * pmouse = (cmouse *)lpvnotifyparameter;
  return(pmouse->mousetransfercomplete());
  }
  // 數(shù)據(jù)傳輸完畢回調(diào)函數(shù)
  dword cmouse::mousetransfercomplete()
  {
  if (m_hevent)
  setevent(m_hevent);
  return 0;
  }
  ulong callback cmouse::mousethreadstub(pvoid context)
  {
  cmouse * pmouse = (cmouse *)context;
  return(pmouse->mousethread());
  }
  // usb鼠標(biāo)線
  dword cmouse::mousethread()
  {
  debugmsg(zone_init,(text(usbmouse: worker thread startedrn)));
  setthreadpriority(getcurrentthread(), thread_priority_highest);
  if (submitinterrupt())
  {
  while (!m_fclosing)
  {
  waitforsingleobject(m_hevent, infinite);
  if (m_fclosing)
  break;
  if ((*m_lpusbfuncs->lpistransfercomplete)(m_hinterrupttransfer))
  {
  if (!handleinterrupt())
  break;
  }
  else
  {
  retailmsg(1,(text(!usbmouse: event signalled, but transfer not completern)));
  // the only time this should happen is if we get an error on the transfer
  assert(m_fclosing || (m_hinterrupttransfer == null));
  break;
  }
  }
  }
  retailmsg(1,(text(usbmouse: worker thread exitingrn)));
  return(0);
  }

  其實(shí)USB的驅(qū)動(dòng)程序編寫就這么簡單,類似的其他設(shè)備,比如打印機(jī)設(shè)備,就有Bulk OUT PIPE,需Bulk傳輸,那就要了解一下IssueBulkTransfer()應(yīng)用。如果是開發(fā)USB Mass Storage Disk的驅(qū)動(dòng),就要了解更多的協(xié)議,如Bulk-Only Transport協(xié)議等。
  微軟的Windows CE.NET的Platform Build中已經(jīng)帶有USB Printer和USB Mass Storage Disk的驅(qū)動(dòng)的源代碼了,好好研究一下,你一定會(huì)受益非淺的。



  
關(guān)鍵詞:驅(qū)動(dòng)

版權(quán)與免責(zé)聲明

凡本網(wǎng)注明“出處:維庫電子市場網(wǎng)”的所有作品,版權(quán)均屬于維庫電子市場網(wǎng),轉(zhuǎn)載請必須注明維庫電子市場網(wǎng),http://m.58mhw.cn,違反者本網(wǎng)將追究相關(guān)法律責(zé)任。

本網(wǎng)轉(zhuǎn)載并注明自其它出處的作品,目的在于傳遞更多信息,并不代表本網(wǎng)贊同其觀點(diǎn)或證實(shí)其內(nèi)容的真實(shí)性,不承擔(dān)此類作品侵權(quán)行為的直接責(zé)任及連帶責(zé)任。其他媒體、網(wǎng)站或個(gè)人從本網(wǎng)轉(zhuǎn)載時(shí),必須保留本網(wǎng)注明的作品出處,并自負(fù)版權(quán)等法律責(zé)任。

如涉及作品內(nèi)容、版權(quán)等問題,請?jiān)谧髌钒l(fā)表之日起一周內(nèi)與本網(wǎng)聯(lián)系,否則視為放棄相關(guān)權(quán)利。

廣告
OEM清單文件: OEM清單文件
*公司名:
*聯(lián)系人:
*手機(jī)號碼:
QQ:
有效期:

掃碼下載APP,
一鍵連接廣大的電子世界。

在線人工客服

買家服務(wù):
賣家服務(wù):
技術(shù)客服:

0571-85317607

網(wǎng)站技術(shù)支持

13606545031

客服在線時(shí)間周一至周五
9:00-17:30

關(guān)注官方微信號,
第一時(shí)間獲取資訊。

建議反饋

聯(lián)系人:

聯(lián)系方式:

按住滑塊,拖拽到最右邊
>>
感謝您向阿庫提出的寶貴意見,您的參與是維庫提升服務(wù)的動(dòng)力!意見一經(jīng)采納,將有感恩紅包奉上哦!