Memonitor USB device / flash disk

March 23, 2009 at 4:56 pm | Posted in Code Samples, Tutorials | 4 Comments
Tags: , , , ,

Oleh Zamrony P. Juhara

USB flash disk adalah perangkat penyimpan data yang ringkas, mungil, mudah dibaca-tulis namun berkapasitas ribuan kali ukuran floppy disk 1.44″. Fitur-fitur ini menyebabkan USB flash disk sangat populer. Kepopuleran USB flash disk menyebabkan pengembang software dituntut mampu mendukung perangkat ini. Banyak software saat ini, terutama software multimedia player, yang menyertakan fitur untuk sinkronisasi data dengan perangkat USB flash disk. Langkah pertama tentu adalah bagaimana mendeteksi jika suatu perangkat USB dicolok atau dilepas.

Artikel ini ditulis untuk menjawab pertanyaan yang diposting oleh anggota mailing list Delphindo seputar bagaimana mendeteksi bila ada USB flash disk yang dipasang atau dilepas ke komputer pada sistem operasi Windows. Detail pertanyaan ada di sini.

WM_DEVICECHANGE

Message WM_DEVICECHANGE akan dikirim ke top-level window ketika terdapat perubahan konfigurasi perangkat keras yang ada pada komputer. Beberapa kejadian yang menyebabkan WM_DEVICECHANGE dikirimkan, salah satunya, adalah perubahan pada removable storage media seperti CD/DVD atau USB flash disk.

Message handler dapat menggunakan parameter WParam untuk menentukan tipe kejadian perubahan perangkat. Beberapa diantaranya adalah:

  • DBT_DEVICEARRIVAL. Perangkat atau media baru saja terpasang dan siap digunakan.
  • DBT_DEVICEREMOVECOMPLETE. Perangkat atau media sukses dilepas.
  • DBT_DEVICEREMOVEPENDING. Perangkat atau media sukses ditunda.
  • DBT_DEVICEQUERYREMOVE. Permintaan ijin bahwa suatu perangkat atau media hendak dilepas. Anda dapat menolak permintaan untuk melepas perangkat atau media. Jika aplikasi Anda sedang mengakses data yang ada di suatu file yang berada di flash disk dan tidak mengijinkan flash disk itu dicabut, Anda dapat membatalkan permintaan itu dengan mengembalikan nilai BROADCAST_DENY_REQUEST. Jika setuju untuk melepas flash disk, isi nilai kembali dengan TRUE.
  • DBT_DEVICEQUERYREMOVEFAILED. Perangkat atau media gagal dilepas.

Turbo Delphi Explorer yang saya pergunakan tidak menyertakan unit berisi deklarasi konstan di atas sehingga harus kita buat sendiri. Kode berikut ini saya hasilkan setelah membaca di website MSDN.

const
  DBT_DEVICEARRIVAL            = $8000;
  DBT_DEVICEQUERYREMOVE        = $8001;
  DBT_DEVICEQUERYREMOVEFAILED  = $8002;
  DBT_DEVICEQUERYREMOVEPENDING = $8002;
  DBT_DEVICEREMOVECOMPLETE     = $8004;

  DBT_DEVTYP_VOLUME            = $00000002;
  DBT_DEVTYP_DEVICEINTERFACE   = $00000005;

Parameter lParam berisi pointer ke data dengan tipe DEV_BROADCAST_HDR. Lebih jauh tentang struktur data ini kita bahas di bagian “Memproses WM_DEVICECHANGE”.

Register dan Unregister Handle Window

Sebenarnya menurut MSDN, WM_DEVICECHANGE ini dikirim ke semua top-level window ketika ada perubahan perangkat pada PC. Namun Windows menyediakan mekanisme baru untuk aplikasi yang ingin memonitor pemasangan/pelepasan perangkat jenis tertentu saja. Mekanisme itu menggunakan RegisterDeviceNotification() dan UnregisterDeviceNotification(). Kedua fungsi tersebut tersedia mulai Windows 2000. Di Delphi deklarasinya ada di unit Windows.pas.

function RegisterDeviceNotification(hRecipient: THandle; 
          NotificationFilter: Pointer; 
          Flags: DWORD): HDEVNOTIFY; stdcall;
function UnregisterDeviceNotification(Handle: HDEVNOTIFY): BOOL; 
          stdcall;

hRecipient adalah handle window yang akan dikirim message WM_DEVICECHANGE. NotificationFilter berisi pointer yang menunjuk ke struktur data bertipe DEV_BROADCAST_DEVICEINTERFACE atau DEV_BROADCAST_VOLUME. Karena yang hendak kita monitor adalah perangkat USB, tipe DEV_BROADCAST_DEVICEINTERFACE kita gunakan. Isi field-field data struktur ini dapat Anda lihat di kode berikut ini.

Contoh pemanggilan untuk registrasi notifikasi perangkat USB.

procedure TUSBDeviceNotifier.InitResources;
var _dev:TDevBroadcastDeviceInterface;
begin
  FWndHandle:=AllocateHwnd(WndProc);

  ZeroMemory(@_dev, sizeOf(TDevBroadcastDeviceInterface));
  with _dev do
  begin
    dbcc_size:=sizeOf(TDevBroadcastDeviceInterface);
    dbcc_devicetype:=DBT_DEVTYP_DEVICEINTERFACE;
    dbcc_reserved:=0;
    dbcc_classguid:= GUID_DEVINTERFACE_USB_DEVICE;
    dbcc_name:=0;
  end;

  FPtrHandle:=RegisterDeviceNotification(FWndHandle,
                          @_dev,
                          DEVICE_NOTIFY_WINDOW_HANDLE);

end;

Pada kode di atas kita daftarkan window untuk mendapatkan notifikasi terkait kejadian-kejadian yang berhubungan dengan perubahan konfigurasi perangkat (DBT_DEVTYP_DEVICEINTERFACE) lebih spesifik lagi yakni perangkat USB (GUID_DEVINTERFACE_USB_DEVICE). GUID ini deklarasinya adalah sebagai berikut:

const
  GUID_DEVINTERFACE_USB_DEVICE: 
     TGUID = '{A5DCBF10-6530-11D2-901F-00C04FB951ED}';

Selanjutnya kita beritahukan Windows, bahwa window dengan handle yang tersimpan di FWndHandle ingin mendapat pemberitahuan bila terdapat kejadian perubahan perangkat USB. Agar Windows tahu bahwa FWndHandle berisi handle window, parameter Flags kita isi dengan DEVICE_NOTIFY_WINDOW_HANDLE.

Jika pemanggilan RegisterDeviceNotification() sukses, fungsi ini akan mengembalikan handle yang dapat Anda pergunakan untuk menghapus dari daftar notifikasi ketika kita sudah tidak membutuhkannya. Lewatkan handle ini ke fungsi UnregisterDeviceNotification().

Memproses WM_DEVICECHANGE

Tiap kali terjadi peruahan konfigurasi perangkat USB, window yang yang Anda daftarkan akan menerima message WM_DEVICECHANGE pada antrian message. Di mana wParam akan diisi dengan tipe kejadian dan lPAram berisi pointer ke struktur data DEV_BROADCAST_HDR. Kode berikut ini adalah contoh bagaimana menangani pesan ini.

procedure TUSBDeviceNotifier.WMDeviceChange(var amsg: TMessage);
begin
  case amsg.WParam of
    DBT_DEVICEARRIVAL:
        DoDeviceArrival(PDevBroadcastHdr(amsg.LParam));
    DBT_DEVICEREMOVECOMPLETE:
        DoDeviceRemoveComplete(PDevBroadcastHdr(amsg.LParam));
  end;
end;

Untuk mendapatkan informasi lebih spesifik, Anda dapat melakukan typecast struktur DEV_BROADCAST_HDR ke struktur lain sesuai jenis tipe device yang Anda monitor. Berhubung kita menggunakan DBT_DEVTYP_DEVICEINTERFACE, maka lParam dapat kita typecast ke DEV_BROADCAST_DEVICEINTERFACE.

Penutup

OK itu saja tips bagaimana mendeteksi apakah ada USB device yang dicolok atau dilepas. Source code demo dapat Anda download di sini. Screenshot demo sederhana ini seperti berikut

USB device arrival/removal detection sedang beraksi

USB device arrival/removal detection sedang beraksi

4 Comments »

RSS feed for comments on this post. TrackBack URI

  1. wah ada panduan deteksi USB nih, keren bang!
    nanti dicoba ah.
    kalo contoh source untuk sistem pakar ada ga?
    bisa di sharing algoritmanya, biar kita tambah pinter😀

  2. minta code buat ngebaca serial number flashdisk yang sesungguhnya, bukan volume serial number. tolong ya butuh buat TA nih dah deadline

  3. tolong banget nih minta source code buat ngebaca serial number yang sesungguhnya dari flashdisk, bukan volume serial number, kirim via email ya jawabannya. please

  4. dah lama aku pikirkan deteksi USB, utak utik disini tibak e ada. yo suwun. aku masih blajar memberdayakan delphi internet, mau aku dikirimi ke hansprg@yahoo.com source program cara buat web server via delphi atau info cara membuat web dan membeli domain syukur gratis yang dekat dengan kota blitar, aq hanya untuk keperluan pribadi seorang guru. terim teman.


Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

Blog at WordPress.com.
Entries and comments feeds.

%d bloggers like this: