BAB V APLIKASI PIC 18F4550 DENGAN KOMPUTER MENGGUNAKAN KELAS HUMAN INTERFACE DEVICE Human Interface Device (HID) merupakan jenis kelas USB yang memperbolehkan vendor pengembang USB untuk membuat aplikasi yang mampu berkomunikasi dengan host tanpa konfigurasi driver yang rumit. Contoh device yang menggunakan kelas USB adalah keyboard, mouse dan joystick. Dalam perkembangannya, beberapa sistem operasi lain (misalnya Linux) juga mendukung sistem HID, namun sebagai host programmer, barangkali akan menemui beberapa tingkat kesulitan dalam memprogram tingkat kernel di sistem operasi tersebut. Berbeda dengan emulating serial over USB, HID tidak membutuhkan driver khusus, sehingga user tinggal menyolokkan konektor USB, lalu konfigurasi yang ada di Microsoft Windows akan berjalan dengan sendirinya. Pertama kali device terdeteksi, Windows akan meminta sistem untuk restart, namun setelah itu Windows akan secara otomatis mendeteksi keberadaan device setelah device terhubung. Jenis kelas HID sangat stabil, namun data buffer input maupun output hanya terbatas 8 byte per transaksi data, sehingga praktis hanya mampu menangani 64 bit data setiap transaksi. Jenis USB ini cocok untuk streaming data yang tidak memerlukan bandwidth lebar (sebatas 8 bit), dan sistem kontrol yang menggunakan interface USB. Sama dengan bab ke-10 aplikasi yang akan kita buat dengan menggunakan kelas HID mempunyai fungsi dan metode yang mirip dengan metode emulating serial over USB. Kode permintaan dari host dilewatkan melalui buffer input device. Selanjutnya data 8 bit yang merupakan informasi dari device ke host dikirimkan melalui buffer output. Lebar buffer input maupun output dapat kita program sendiri. Nilai ini akan mempengaruhi jumlah endpoint pada PIC18F4550. Descriptor string dapat kita program pada PIC dan nilai string inilah yang akan muncul pertama kali pada saat device terhubung ke host/PC. Dalam pemrograman kelas HID semua pertukaran data berada dalam sebuah struktur yang diinisialisasikan dengan istilah report. Host mengirimkan dan menerima data dengan mengirim dan meminta report pada transfer kontrol dan interrupt. Format report fleksibel dan berisi apapun jenis data dengan ukuran byte yang telah ditentukan. Transfer kontrol mengandung permintaan Set_Report dan Get_Report yang berfungsi menyediakan jalan untuk host dan device untuk melakukan transfer report. Host menggunakan Set_Report untuk mengirimkan report dan Get_Report untuk menerima report. Set_Idle dan Get_Idle mengeset dan membaca kondisi idle yang akan menyatakan perlu tidaknya device mengirimkan ulang data setelah polling. Set_Protocol dan Get_protocol berfungsi untuk mengeset serta membaca nilai protokol yang akan mengenabel device ke sebuah fungsi dengan protokol yang lebih simple, seperti pada kondisi boot-up pada Windows. Transfer interrupt HID menyediakan sebuah alternatif dalam pertukaran data terutama ketika penerima harus mendapatkan data dengan cepat atau secara periodik. Transfer kontrol dapat tertunda jika keadaan bus sedang sibuk, sementara bandwidth untuk transfer interrupt masih tersedia ketika proses konfigurasi device.
HARDWARE DAN DESAIN KOMUNIKASI HOST-DEVICE Project HID kali ini mempunyai tujuan yang sama yaitu membaca 4 kanal analog input, membaca Port B dan menulis Port D, namun tentu saja dengan kelas komunikasi HID. Gambar rangkaian untuk sistem yang akan kita buat masih sama dengan rangkaian pada Bab 10, CDC emulating serial over USB. Gambar rangkaian untuk project kita kali ini (HID_ku) mengacu pada Gambar 4.1 (pada bab 10) Komunitas eLearning IlmuKomputer.Com Copyright © 2003-2007 IlmuKomputer.Com
75
Rancangan sistem komunikasi antara host dengan device jelas berbeda dikarenakan kelas HID hanya mampu mengusung 8 byte dalam setiap transaksi (Hid_report_in). Untuk mengatasi hal ini, maka data 9 byte yang berisi nilai ADC dan nilai PortB dipecah menjadi 2 transaksi seperti pada Gambar 5.1. Permintaan host ke device tidak menggunakan karakter ASCII “A”, atau , “C” (pada bab ke-10), namun menggunakan kode nilai 1H, 2H (bukan ASCII), serta karakter untuk menghidupmatikan Port D. 1H
Nilai 4 saluran ADC (8 byte) 2H
4 X Analog Input (0-5V) [8 byte] + Input 8 bit / PortB [1 byte] à 9 byte
1 byte nilai PortB + 7 byte sisa (8 byte)
Komputer sebagai Host (Aplikasi VB)
Data 1 byte : p/P/q/Q/r/R/s/S/t /T/u/U/v/V/w/W
8 bit Output PIC18F4550 sebagai device
: hid_report_out[1byte] : hid_report_in[8byte]
Gambar 5.1 Gambar Desain Komunikasi Antara Host–Device
Kelas HID menggunakan sistem LoopBack dalam setiap proses transaksi. Proses pembacaan I/O termasuk ADC juga dilakukan dalam rutin LoopBack yang sama. Sisi positifnya, ketika mikrokontroler mengalami POR (Power On Reset) sampai adanya kegagalan koneksi pada jalur USB, jalur program akan kembali ke proses inisialisasi sistem dilanjutkan melakukan pembacaan dan penulisan I/O secara terus menerus sehingga jikalau koneksi sudah baik, aplikasi juga berjalan normal lagi. Kelemahannya, karena menggunakan sistem LoopBack, data yang dibawa juga terbatas, karena harus memperhitungkan waktu tunda interrupt. Oleh karena itu, nilai 9 byte pada project yang kita bangun dipecah menjadi 2 bagian. Delapan byte pertama berisi nilai pembacaan ADC 4 saluran, yang masing-masing berisi data 10 bit pembacaan ADC, sedangkan nilai PortB (1 byte) dikirimkan bersama 7 byte lainnya yang tidak terpakai untuk menjaga nilai hid_report_in tetap sebesar 8 byte. Tujuh byte yang tidak terpakai tersebut diisi nilai 0H pada program hid_application.c. Pada sistem LoopBack project yang kita rancang, device akan mempunyai aksi sebagai berikut : 1. Jika nilai hid_report_out = 1H maka nilai hid_report_in (nilai “in” dan “out” dipandang dari sisi host) akan berisi : ADC channel ke-0 + ADC channel ke-1 + ADC channel ke-2 + ADC channel ke-3. 2. Jika nilai hid_report_out = 2H maka akan nilai hid_report_in akan berisi : nilai PortB + nilai 7 byte berisi nilai 0H (agar total hid_report_in tetap 8 byte) 3. Jika nilai hid_report_out = “P” (ASCII), Port D0 akan bernilai 1 4. Jika nilai hid_report_out = “p” (ASCII), Port D0 akan bernilai 0 5. Jika nilai hid_report_out = “Q” (ASCII), Port D1 akan bernilai 1 6. Jika nilai hid_report_out = “q” (ASCII), Port D1 akan bernilai 0 7. Jika nilai hid_report_out = “R” (ASCII), Port D2 akan bernilai 1 8. Jika nilai hid_report_out = “r” (ASCII), Port D2 akan bernilai 0 9. Jika nilai hid_report_out = “S” (ASCII), Port D3 akan bernilai 1 10. Jika nilai hid_report_out = “s” (ASCII), Port D3 akan bernilai 0 Komunitas eLearning IlmuKomputer.Com Copyright © 2003-2007 IlmuKomputer.Com
76
11. Jika nilai hid_report_out = “T” (ASCII), Port D4 akan bernilai 1 12. Jika nilai hid_report_out = “t” (ASCII), Port D4 akan bernilai 0 13. Jika nilai hid_report_out = “U” (ASCII), Port D5 akan bernilai 1 14. Jika nilai hid_report_out = “u” (ASCII), Port D5 akan bernilai 0 15. Jika nilai hid_report_out = “V” (ASCII), Port D6 akan bernilai 1 16. Jika nilai hid_report_out = “v”, (ASCII) Port D6 akan bernilai 0 17. Jika nilai hid_report_out = “W”(ASCII), Port D7 akan bernilai 1 18. Jika nilai hid_report_out = “w”(ASCII), Port D7 akan bernilai 0 Jika dibandingkan dengan metode emulating serial over USB pada bab ke-10, terdapat kesamaan dalam proses komunikasi, yaitu menggunakan kode-kode untuk saling berkomunikasi. Kode-kode tersebut sifatnya bebas dan tergantung dari perancang komunikasi host device.
FIRMWARE Firmware pada device dibuat agar device yang terdeteksi merupakan kelas HID. Descriptor pada device harus mengandung sebuah descriptor interface yang menyatakan sebuah descriptor HID dan sebuah descriptor endpoint interrupt IN. HID dapat mendukung satu atau lebih report. Descriptor report menyatakan ukuran dan isi dari data. Nilai descriptor menetukan setiap report Input, Output atau Feature. Host akan menerima data pada report Input, dan mengirimkan data pada report Output. Report Feature dapat mengalir dalam dua arah. Device harus mendukung sedikitnya satu report Input, sedangkan report Output sifatnya tergatung kebutuhan (tidak wajib). Pada descriptor interface, nilai bInterfaceclass = 3 akan mengakibatkan identifikasi interface sebagai HID. Jika nilai bInterfaceSubClass = 1 artinya device mendukung boot interface yang mampu berjalan tanpa driver pada host. Keadaan ini diperlukan ketika komputer memasuki area DOS, atau ketika boot up pertama kali, atau dalam keadaan Windows save mode. Karena device yang kita rancang tidak memerlukan fasilitas ini, maka nilai bInterfaceSubClass = 0. Descriptor kelas HID terdiri dari 7 atau lebih bagian tergantung dari nomor tambahan descriptor, seperti ditunjukkan oleh Tabel 5.1. Offset (desimal) 0
bLength
Ukuran (byte) 1
1
bDescriptorType
1
2
bcdHID
2
4
bCountryCode
1
5
bNumDescriptor
1
6
bDescriptorType
1
7
wDescriptorLength
2
9
bDescriptorType
1
10
wDescriptorLength
2
Bagian
Keterangan Ukuran descriptor Jenis descriptor : bernilai 21H agar terdeteksi sebagai kelas HID Nomor release versi HID Nomor identifikasi lokasi negara pembuat device Nomor report subordinat dan descriptor fisik Jenis descriptor kelas khusus yang mengikuti Lebar total string pada bDescriptorType Jenis descriptor kelas khusus. Lebar total string pada descriptor.
Tabel 5.1. Daftar Descriptor Pada Kelas HID Komunitas eLearning IlmuKomputer.Com Copyright © 2003-2007 IlmuKomputer.Com
77
Semua kelas HID harus mendukung Get_Report dan device dengan fasilitas boot HID harus mendukung pula Get_Protocol dan Set_Protocol. Jenis permintaan yang lain (Set_report, Get_Idle, dan Set_Idle) bersifat tidak wajib kecuali HID yang mendukung protokol boot-up harus mendukung Set_Idle. Permintaan data pada HID dibedakan menjadi 6 bagian seperti dalam Tabel 5.2. Semua permintaan tersebut berasal dari host dan direspon oleh device. Dalam tabel terdapat kolom sumber data yang tidak sama dengan sumber permintaan (sumber request). Permintaan data tersebut pada praktiknya berupa fungsi-fungsi dan rutin pemrograman, baik dari sisi host (VB6) ataupun device (MPLAB IDE dengan kompiler Microchip C18). Microchip telah memberikan beberapa contoh kelas HID yang dapat kita modifikasi sesuai dengan keperluan. Contoh kelas HID ada di Microchip USB Framework yang saat ini sampai pada USB FrameWork versi 2.6. Yang akan kita gunakan adalah USB Framework versi 2.1. Penggunaan USB framework khususnya kelas HID untuk keperluan demo antarmuka USB sebuah mouse dapat kita peroleh di situs www.microchip.com. Acuan dari buku menggunakan Microchip USB FrameWork versi 2.1.
01h
Get_Report
Sumber data pada sesi DATA Device
report type
interface
02h
Get_Idle
Device
report ID
interface
1
03h
Get_Protocol
Device
0, report ID
interface
09h
Set_report
Host
0
interface
1 lebar report
Nomor Permintaan (bRequest)
Jenis
0Ah
Set_Idle
-
0Bh
Set_Protocol
-
wValue
wIndex
durasi idle, report ID 0, protokol
Lebar Data (byte)
Konten report durasi selama idle protokol report
interface
-
-
interface
-
-
Tabel 5.2 Jenis Permintaan Data Pada Kelas HID
Pada project yang kita buat (nama project: HID_ku), agar lebih mudah dalam mengelompokkan file-file dalam satu project, pertama kali kita buatlah folder dengan nama HID_ku di directory C:¥. Seperti halnya pada bab 10, maka di bawah folder HID_ku kita buat lagi beberapa folder sebagai berikut : •
Source (C:¥HID_ku¥Source) untuk menaruh file source yang berektensi *.c
•
Header (C:¥HID_ku¥Header) untuk menaruh file header yang berektensi *.h
•
Linker (C:¥HID_ku¥Linker) untuk menaruh file Linker yang berektensi *.lkr
•
Output (C:¥HID_ku¥Output) untuk meletakkan semua output dan file keterangan kompile program berupa file dengan ekstensi *.o, *.map, dan *.hex
Melalui MPLAB IDE (dengan kompiler Microchip C18), buatlah sebuah project dengan nama “HID_ku.mcp”. Settingan untuk path directory project diatur dengan cara sebagai berikut: Project > Build Options > Project … Pada tab Directories pengaturan path adalah sebagai berikut : •
Output Directories :
C:¥HID_ku¥Output
•
Intermediary Directory : C:¥HID_ku¥Output
•
Include Search Path : C:¥mcc18¥lib
•
Library Search Path : C:¥MCC18¥lib
•
Linker-script Search Path : C:¥HID_ku¥Linker
Komunitas eLearning IlmuKomputer.Com Copyright © 2003-2007 IlmuKomputer.Com
;
C:¥mcc18 ; C:¥HID_ku
78
Dengan berbasiskan kompiler Microchip C18, berikut ini merupakan file yang diperlukan untuk membentuk projek HID_ku, beserta kode yang diperlukan. 1. hid_application.c (C:\HID_ku\Source) File hid_application.c merupakan file modifikasi mouse.c yang merupakan framework USB dari Microchip dan dimodifikasi agar bisa menjalankan mikrokontroler dan berinteraksi dengan Analog Input dan I/O. Penamaan IN dan OUT dilihat dari sisi host, bukan dari device. Misalnya hid_report_in, maka analogi “in” adalah sebagai input bagi host. /************************************************************** FileName: generic_hid.c (pure) (c) Microhip Corp. 1.0 5/5/2008 Converted Microchip's mouse.c for use in a generic HID (Jan Axelson) 1.1 6/21/08 Reports are 8 bytes each. Revised ReportLoopback routine. //Diubah menyesuaikan fungsi PIC18F4550 /** INCLUDES *******************************************************/ #include "header/GenericTypeDefs.h" #include "header/Compiler.h" #include "header/usb_config.h" #include "header/usb_device.h" #include "header/usb.h" #include "header/hid_application.h" #include "header/HardwareProfile.h" // Untuk ADC #include
#include <stdlib.h> #include <delays.h> //************************************************************** /** CONFIGURATION ********************************************/ #if defined(PICDEM_FS_USB) // PIC18F4550 is used #pragma config PLLDIV = 5 // (20 MHz input) #pragma config CPUDIV = OSC1_PLL2 #pragma config USBDIV = 2 // Clock source from 96MHz PLL/2 #pragma config FOSC = HSPLL_HS #pragma config IESO = OFF #pragma config PWRT = ON #pragma config BOR = ON #pragma config BORV = 2 #pragma config VREGEN = ON #pragma config WDT = OFF #pragma config MCLRE = ON #pragma config LPT1OSC = OFF #pragma config PBADEN = OFF #pragma config STVREN = ON #pragma config LVP = OFF #pragma config ICPRT = OFF // Dedicated In-Circuit Debug #pragma config XINST = OFF // Extended Instruction Set #pragma config WRTC = OFF #pragma config WRT0 = OFF #pragma config WRT1 = OFF #pragma config WRTB = OFF // Boot Blok Write Protection #pragma config CP0 = OFF #pragma config CP1 = OFF #pragma config CPB = OFF #elif defined(PIC18F87J50_PIM) #pragma config PLLDIV = 3 #pragma config CPUDIV = OSC1 #pragma config FOSC = HSPLL #pragma config IESO = OFF
Komunitas eLearning IlmuKomputer.Com Copyright © 2003-2007 IlmuKomputer.Com
79
#pragma config WDTEN = OFF #pragma config XINST = OFF #pragma config CP0 = OFF #pragma config MODE = MM
// Extended Instruction Set
#elif defined(EXPLORER_16) #ifdef __PIC24FJ256GB110__ _CONFIG1( JTAGEN_OFF & GCP_OFF & GWRP_OFF & COE_OFF & FWDTEN_OFF & ICS_PGx2 & IOL1WAY_ON) _CONFIG2( 0xF7FF & IESO_OFF & FCKSM_CSDCMD & OSCIOFNC_OFF & POSCMOD_HS & FNOSC_PRIPLL & PLLDIV_DIV2) #else #error No hardware board defined, see "HardwareProfile.h" and __FILE__ #endif #else #error No hardware board defined, see "HardwareProfile.h" and __FILE__ #endif /** VARIABLES **********************************************/ #pragma udata BYTE old_sw2,old_sw3; USB_HANDLE lastTransmission = 0; USB_HANDLE lastOutTransmission = 0; char usb_state = 'r'; BYTE AN0L,AN0H,AN1L,AN1H,AN2L,AN2H,AN3L,AN3H; BYTE nilai_portB; /** PRIVATE PROTOTYPES *************************************/ void BlinkUSBStatus(void); BOOL Switch2IsPressed(void); BOOL Switch3IsPressed(void); static void InitializeSystem(void); void konversiADC0 (void); void konversiADC1 (void); void konversiADC2 (void); void konversiADC3 (void); /** VECTOR REMAPPING ***************************************/ #if defined(__18CXX) extern void _startup (void);//See c018i.c in C18 compiler dir #pragma code _RESET_INTERRUPT_VECTOR = 0x000800 //<<*** FOR CORRECT STARTUP W/USB BOOTLOADER @ 800h void _reset (void) { _asm goto _startup _endasm } #pragma code #endif /** DECLARATIONS *********************************************/ #pragma code /**************************************************************** * Function: void ReportLoopback(void) * Side Effects: The ownership of the USB buffers will change according * to the required operation * Overview: This routine will send a received Input report back * to the host in an Output report. * Both directions use interrupt transfers. *****************************************************************/ void ReportLoopBack(void) { BYTE count = 0; switch (usb_state) {
Komunitas eLearning IlmuKomputer.Com Copyright © 2003-2007 IlmuKomputer.Com
80
case 'r': { if(HIDRxHandleBusy(lastOutTransmission) == 0) { lastOutTransmission = HIDRxPacket(HID_EP, (BYTE*)&hid_report_out, 64); usb_state = 'p'; } break; } case 'p': { if(HIDRxHandleBusy(lastOutTransmission) == 0) { if (lastOutTransmission->CNT > 0) { for (count; count <= HID_OUTPUT_REPORT_BYTES - 1; count++) { TRISB = 0b11111111; TRISD = 0; nilai_portB = PORTB ; konversiADC0(); konversiADC1(); konversiADC2(); konversiADC3(); if (hid_report_out[0] == 1) //first 8 bytes { hid_report_in[0] = AN0L; hid_report_in[1] = AN0H; hid_report_in[2] = AN1L; hid_report_in[3] = AN1H; hid_report_in[4] = AN2L; hid_report_in[5] = AN2H; hid_report_in[6] = AN3L; hid_report_in[7] = AN3H; } if (hid_report_out[0] == 2) //secondly 8 bytes { hid_report_in[0] = nilai_portB; hid_report_in[1] = 0; hid_report_in[2] = 0; hid_report_in[3] = 0; hid_report_in[4] = 0; hid_report_in[5] = 0; hid_report_in[6] = 0; hid_report_in[7] = 0; } if (hid_report_out[0] == 'P') { PORTDbits.RD0= 1; } if (hid_report_out[0] == 'p') { PORTDbits.RD0= 0; } if (hid_report_out[0] == 'Q') { PORTDbits.RD1= 1; } if (hid_report_out[0] == 'q') { PORTDbits.RD1= 0; } if (hid_report_out[0] == 'R') {
Komunitas eLearning IlmuKomputer.Com Copyright © 2003-2007 IlmuKomputer.Com
81
PORTDbits.RD2= 1; } if (hid_report_out[0] == 'r') { PORTDbits.RD2= 0; } if (hid_report_out[0] == 'S') { PORTDbits.RD3= 1; } if (hid_report_out[0] == 's') { PORTDbits.RD3= 0; } if (hid_report_out[0] == 'T') { PORTDbits.RD4= 1; } if (hid_report_out[0] == 't') { PORTDbits.RD4= 0; } if (hid_report_out[0] == 'U') { PORTDbits.RD5= 1; } if (hid_report_out[0] == 'u') { PORTDbits.RD5= 0; } if (hid_report_out[0] == 'V') { PORTDbits.RD6= 1; } if (hid_report_out[0] == 'v') { PORTDbits.RD6= 0; } if (hid_report_out[0] == 'W') { PORTDbits.RD7= 1; } if (hid_report_out[0] == 'w') { PORTDbits.RD7= 0; } // Ready to transmit the received data back to the host. usb_state = 't'; } else { // No data was received. Return checking for new received data. usb_state = 'r'; } } break; } case 't': { if (HIDTxHandleBusy(lastTransmission) == 0) { // The CPU owns the endpoint.
Komunitas eLearning IlmuKomputer.Com Copyright © 2003-2007 IlmuKomputer.Com
82
// Prepare to send data. lastTransmission = HIDTxPacket(HID_EP, (BYTE*)&hid_report_in, HID_INPUT_REPORT_BYTES); // Return to checking for new received data. usb_state = 'r'; } break; } default: { break; } } }//end ReportLoopback /****************************************************************************** * Function: BOOL Switch2IsPressed(void) * Overview: Indicates if the switch is pressed. *****************************************************************************/ BOOL Switch2IsPressed(void) { if(sw2 != old_sw2) { old_sw2 = sw2; // Save new value if(sw2 == 0) // If pressed return TRUE; // Was pressed }//end if return FALSE; // Was not pressed }//end Switch2IsPressed /****************************************************************************** * Function: BOOL Switch3IsPressed(void) * Output: TRUE - pressed, FALSE - not pressed *****************************************************************************/ BOOL Switch3IsPressed(void) { if(sw3 != old_sw3) { old_sw3 = sw3; // Save new value if(sw3 == 0) // If pressed return TRUE; // Was pressed }//end if return FALSE; // Was not pressed }//end Switch3IsPressed /******************************************************************** * Function: void BlinkUSBStatus(void) * Overview: BlinkUSBStatus turns on and off LEDs * corresponding to the USB device state. * Note: mLED macros can be found in HardwareProfile.h * USBDeviceState is declared and updated in * usbd.c. *******************************************************************/ void BlinkUSBStatus(void) { static WORD led_count=0; if(led_count == 0)led_count = 10000U; led_count--; #define mLED_Both_Off() {mLED_1_Off();mLED_2_Off();} #define mLED_Both_On() {mLED_1_On();mLED_2_On();} #define mLED_Only_1_On() {mLED_1_On();mLED_2_Off();} #define mLED_Only_2_On() {mLED_1_Off();mLED_2_On();} if(USBSuspendControl == 1) {
Komunitas eLearning IlmuKomputer.Com Copyright © 2003-2007 IlmuKomputer.Com
83
if(led_count==0) { mLED_1_Toggle(); mLED_2 = mLED_1; } //end if
// Both blink at the same time
} else {
} }
if(USBDeviceState == DETACHED_STATE) { mLED_Both_Off(); } else if(USBDeviceState == ATTACHED_STATE) { mLED_Both_On(); } else if(USBDeviceState == POWERED_STATE) { mLED_Only_1_On(); } else if(USBDeviceState == DEFAULT_STATE) { mLED_Only_2_On(); } else if(USBDeviceState == ADDRESS_STATE) { if(led_count == 0) { mLED_1_Toggle(); mLED_2_Off(); } //end if } else if(USBDeviceState == CONFIGURED_STATE) { if(led_count==0) { mLED_1_Toggle(); mLED_2 = !mLED_1; // Alternate blink } //end if } //end if(....) //end if(UCONbits.SUSPND....) //end BlinkUSBStatus
/******************************************************************** * Function: void ProcessIO(void) * Overview: This function is a place holder for other user * routines. It is a mixture of both USB and * non-USB tasks. *******************************************************************/ void ProcessIO(void) { if((USBDeviceState < CONFIGURED_STATE)||(USBSuspendControl==1)) return; ReportLoopBack(); } //end ProcessIO /******************************************************************** * Function: static void InitializeSystem(void) * Overview: InitializeSystem is a centralize initialization * routine. All required USB initialization routines * are called from here. * * User application initialization routine should * also be called from here. *******************************************************************/
Komunitas eLearning IlmuKomputer.Com Copyright © 2003-2007 IlmuKomputer.Com
84
static void InitializeSystem(void) { #if (defined(__18CXX) & !defined(PIC18F87J50_PIM)) ADCON1 |= 0x0F; // Default all pins to digital #elif defined(__C30__) AD1PCFG = 0xFFFF; #endif #if defined(PIC18F87J50_PIM) { unsigned int pll_startup_counter = 600; OSCTUNEbits.PLLEN = 1; //Enable the PLL and wait 2+ms until the //PLL locks before enabling USB module while(pll_startup_counter--); } WDTCONbits.ADSHR = 1; // Select alternate SFR location to access ANCON ANCON0 = 0xFF; // Default all pins to digital ANCON1 = 0xFF; // Default all pins to digital WDTCONbits.ADSHR = 0; // Select normal SFR locations #endif USBDeviceInit(); }//end InitializeSystem /******************************************************************** * Function: void main(void) * Overview: Main program entry point. *******************************************************************/ #if defined(__18CXX) void main(void) #else int main(void) #endif { InitializeSystem(); while(1) { // Check bus status and service USB interrupts. USBDeviceTasks(); // Interrupt or polling method // Application-specific tasks. ProcessIO(); } //end while } //end main void USBCBSuspend(void) { #if defined(__C30__) #if 0 U1EIR = 0xFFFF; U1IR = 0xFFFF; U1OTGIR = 0xFFFF; IFS5bits.USB1IF = 0; IEC5bits.USB1IE = 1; U1OTGIEbits.ACTVIE = 1; U1OTGIRbits.ACTVIF = 1; TRISA &= 0xFF3F; LATAbits.LATA6 = 1; Sleep(); LATAbits.LATA6 = 0; #endif #endif } #if 0
Komunitas eLearning IlmuKomputer.Com Copyright © 2003-2007 IlmuKomputer.Com
85
void __attribute__ ((interrupt)) _USB1Interrupt(void) { #if !defined(self_powered) if(U1OTGIRbits.ACTVIF) { LATAbits.LATA7 = 1; IEC5bits.USB1IE = 0; U1OTGIEbits.ACTVIE = 0; IFS5bits.USB1IF = 0; USBClearInterruptFlag(USBIdleIFReg,USBIdleIFBitNum); LATAbits.LATA7 = 0; } #endif } #endif void USBCBWakeFromSuspend(void) { } /******************************************************************** * Function: void konversi ADC * Overview: Rutine for ADC *******************************************************************/ void konversiADC0 (void) { OpenADC( ADC_FOSC_32 & ADC_RIGHT_JUST & ADC_12_TAD, ADC_CH0 & ADC_VREFPLUS_VDD& ADC_VREFMINUS_VSS& ADC_INT_OFF, 11 ); Delay10TCYx( 5 ); ConvertADC(); // Start conversion while( BusyADC() ); // Wait for completion ReadADC(); AN0H = ADRESH; AN0L = ADRESL; CloseADC(); // Disable A/D converter } void konversiADC1 (void) { OpenADC( ADC_FOSC_32 & ADC_RIGHT_JUST & ADC_12_TAD, ADC_CH1 & ADC_VREFPLUS_VDD& ADC_VREFMINUS_VSS& ADC_INT_OFF, 11 ); Delay10TCYx( 5 ); ConvertADC(); while( BusyADC() ); ReadADC(); AN1H = ADRESH; AN1L = ADRESL; CloseADC();
// Start conversion // Wait for completion
// Disable A/D converter } void konversiADC2 (void) { OpenADC( ADC_FOSC_32 & ADC_RIGHT_JUST & ADC_12_TAD, ADC_CH2 & ADC_VREFPLUS_VDD& ADC_VREFMINUS_VSS& ADC_INT_OFF, 11 ); Delay10TCYx( 5 ); ConvertADC(); while( BusyADC() ); ReadADC(); AN2H = ADRESH; AN2L = ADRESL; CloseADC();
// Start conversion // Wait for completion
// Disable A/D converter
} void konversiADC3 (void) {
Komunitas eLearning IlmuKomputer.Com Copyright © 2003-2007 IlmuKomputer.Com
86
OpenADC( ADC_FOSC_32 & ADC_RIGHT_JUST & ADC_12_TAD, ADC_CH3 & ADC_VREFPLUS_VDD& ADC_VREFMINUS_VSS& ADC_INT_OFF, 11 ); Delay10TCYx( 5 ); ConvertADC(); while( BusyADC() ); ReadADC(); AN3H = ADRESH; AN3L = ADRESL; CloseADC();
// Start conversion // Wait for completion
// Disable A/D converter
} void inisialisasi_port (void) { TRISA = 0b11111111; TRISD = 0b00000000; TRISBbits.TRISB0=1; TRISBbits.TRISB1=1; TRISBbits.TRISB2=1; TRISBbits.TRISB3=1; } /******************************************************************** * Function: void USBCB_SOF_Handler(void) * Overview: The USB host sends out a SOF packet to full-speed * devices every 1 ms. This interrupt may be useful * for isochronous pipes. End designers should * implement callback routine as necessary. *******************************************************************/ void USBCB_SOF_Handler(void) { } /******************************************************************* * Function: void USBCBErrorHandler(void) * Overview: The purpose of this callback is mainly for * debugging during development. Check UEIR to see * which error causes the interrupt. *******************************************************************/ void USBCBErrorHandler(void) { } /******************************************************************* * Function: void USBCBErrorHandler(void) * Overview: The purpose of this callback is mainly for * debugging during development. Check UEIR to see * which error causes the interrupt. *******************************************************************/ void USBCBCheckOtherReq(void) { USBCheckHIDRequest(); } //end void USBCBStdSetDscHandler(void) { } //end /******************************************************************* * Function: void USBCBInitEP(void) * Overview: This function is called when the device becomes * initialized. This should initialize the endpoints * for the device's usage according to the current * configuration.
Komunitas eLearning IlmuKomputer.Com Copyright © 2003-2007 IlmuKomputer.Com
87
*******************************************************************/ void USBCBInitEP(void) { //enable the HID endpoint USBEnableEndpoint(HID_EP,USB_IN_ENABLED|USB_OUT_ENABLED | USB_HANDSHAKE_ENABLED|USB_DISALLOW_SETUP); } /******************************************************************** * Function: void USBCBSendResume(void) * Overview: This callback should send a RESUME signal that *******************************************************************/ void USBCBSendResume(void) { static WORD delay_count; USBResumeControl = 1; // Start RESUME signaling delay_count = 1800U; // Set RESUME line for 1-13 ms do { delay_count--; }while(delay_count); USBResumeControl = 0; } /****************************************************************************** * Function: void HandleControlOutReport(void) * Overview: Checks to see if an Output or Feature report has arrived * on the control pipe. If yes, extracts and uses the data. *****************************************************************************/ void HandleControlOutReport(void) { BYTE count = 0; switch (MSB(SetupPkt.W_Value)) { case 0x02: // Output report { switch(LSB(SetupPkt.W_Value)) { case 0: // Report ID 0 for (count = 0; count <= HID_OUTPUT_REPORT_BYTES - 1; count++) { // Copy data from the control transfer's buffer to hid_report_in. hid_report_in[count] = CtrlTrfData[count]; } break; } // end switch(LSB(SetupPkt.W_Value)) break; } case 0x03: // Feature report { // Get the report ID from the Setup packet. switch(LSB(SetupPkt.W_Value)) { case 0: // Report ID 0 for (count = 0; count <= HID_FEATURE_REPORT_BYTES - 1; count++) { hid_report_feature[count] = CtrlTrfData[count]; } break; } // end switch(LSB(SetupPkt.W_Value)) break; }
Komunitas eLearning IlmuKomputer.Com Copyright © 2003-2007 IlmuKomputer.Com
88
} }
// end switch(MSB(SetupPkt.W_Value)) // end HandleControlOutReport
/****************************************************************************** * Function: BOOL ReportSupported(void) * Output: TRUE if the report is supported, otherwise FALSE. *****************************************************************************/ BOOL ReportSupported(void) { switch (MSB(SetupPkt.W_Value)) { case 0x02: // Output report { switch(LSB(SetupPkt.W_Value)) { case 0x00: // Report ID 0 { return TRUE; } default: { return FALSE; } } // end switch(LSB(SetupPkt.W_Value)) } case 0x03: // Feature report { switch(LSB(SetupPkt.W_Value)) { case 0x00: // Report ID 0 { return TRUE; } default: { // Other report IDs not supported. return FALSE; } } // end switch(LSB(SetupPkt.W_Value)) } default: { return FALSE; } } // end switch(MSB(SetupPkt.W_Value)) } // end ReportSupported
2. usb_descriptors.c (C:\HID_ku\Source) Pada file usb_descriptor.c kita dapat menentukan nilai Product dan Vendor ID, tentu saja lisensi dari nomor yang kita buat diatur oleh USBIF (www.usb.org) agar tidak mengalami bentrok dengan nomor vendor lain. Dalam contoh kali ini nilai vendor ID adalah 0900H dan nilai Product ID nya 0100H. (baris 29 dan 30 pada Gambar 5.2)
Komunitas eLearning IlmuKomputer.Com Copyright © 2003-2007 IlmuKomputer.Com
89
Gambar 5.2 Penentuan Produk ID dan Vendor ID yang berisi empat bilangan heksa pada kelas HID.
Descriptor string terdiri atas Manufacturer dan Product. Keduanya muncul sebagai identitas device oleh host. Nilai report output adalah 1. Hal itu dikarenakan host tidak akan mengirimkan lebih sari satu byte kode untuk meminta report in pada device. Sedangkan nilai report input di set ke 8 byte karena digunakan untuk mantransfer data sejumlah 8 byte (Gambar 5.3 lihat baris ke-111). Nilai kedua report tersebut disesuaikan dengan kebutuhan transaksi data.
Gambar 5.3. Descriptor String dan penentuan nilai Report IN, OUT dan Feature
Kode untuk usb_descriptor .c adalah sebagai berikut : #ifndef __USB_DESCRIPTORS_C #define __USB_DESCRIPTORS_C /** INCLUDES *******************************************************/ #include "header/GenericTypeDefs.h" #include "header/Compiler.h" #include "header/usb_config.h" #include "header/usb_device.h" /** CONSTANTS ******************************************************/ #if defined(__18CXX) #pragma romdata #endif /* Device Descriptor */ ROM USB_DEVICE_DESCRIPTOR device_dsc= { 0x12, // Size of this descriptor in bytes USB_DESCRIPTOR_DEVICE, // DEVICE descriptor type 0x0110, // USB Spec Release Number in BCD format 0x00, // Class Code
Komunitas eLearning IlmuKomputer.Com Copyright © 2003-2007 IlmuKomputer.Com
90
0x00, 0x00, EP0_BUFF_SIZE, 0x0900, 0x0100, 0x0001, 0x01, 0x02, 0x00, 0x01
// Subclass code // Protocol code // Max packet size for EP0, see usbcfg.h // Vendor ID // Product ID // Device release number in BCD format // Manufacturer string index // Product string index // Device serial number string index // Number of possible configurations
}; /* Configuration 1 Descriptor */ ROM BYTE configDescriptor1[]={ /* Configuration Descriptor */ 0x09, // Size of this descriptor in bytes USB_DESCRIPTOR_CONFIGURATION, // CONFIGURATION descriptor type 0x29,0x00, // Total length of data for this cfg 1, // Number of interfaces in this cfg 1, // Index value of this configuration 0, // Configuration string index _DEFAULT|_SELF, // Attributes, see usbd.h 50, // Max power consumption (2X mA) /* Interface Descriptor */ 0x09, //sizeof(USB_INTF_DSC), // Size of this descriptor in bytes USB_DESCRIPTOR_INTERFACE, // INTERFACE descriptor type 0, // Interface Number 0, // Alternate Setting Number 2, // Number of endpoints in this intf HID_INTF, // Class code 0, // Subclass code 0, // Protocol code 0, // Interface string index /* HID Class-Specific Descriptor */ 0x09,//sizeof(USB_HID_DSC)+3, // Size of this descriptor in bytes RRoj hack DSC_HID, // HID descriptor type 0x11,0x01, // HID Spec Release Number in BCD format (1.11) 0x00, // Country Code (0x00 for Not supported) HID_NUM_OF_DSC, // Number of class descriptors, see usbcfg.h DSC_RPT, // Report descriptor type 47,0x00, //sizeof(hid_rpt01), // Size of the report descriptor /* Endpoint Descriptor */ 0x07, /*sizeof(USB_EP_DSC)*/ USB_DESCRIPTOR_ENDPOINT, //Endpoint Descriptor HID_EP | _EP_IN, //EndpointAddress _INT, //Attributes 0x08,0x00, //size 0x0A, //Interval /* Endpoint Descriptor */ 0x07, /*sizeof(USB_EP_DSC)*/ USB_DESCRIPTOR_ENDPOINT, //Endpoint Descriptor HID_EP | _EP_OUT, //EndpointAddress _INT, //Attributes 0x08,0x00, //size 0x0A //Interval }; //Language code string descriptor ROM struct{BYTE bLength;BYTE bDscType;WORD string[1];}sd000={ sizeof(sd000),USB_DESCRIPTOR_STRING,{0x0409 }}; //Manufacturer string descriptor ROM struct{BYTE bLength;BYTE bDscType;WORD string[11];}sd001={ sizeof(sd001),USB_DESCRIPTOR_STRING, {'D','a','t','a',' ','V','i','s','i','o ','n' }};
Komunitas eLearning IlmuKomputer.Com Copyright © 2003-2007 IlmuKomputer.Com
91
//Product string descriptor ROM struct{BYTE bLength;BYTE bDscType;WORD string[15];}sd002={ sizeof(sd002),USB_DESCRIPTOR_STRING, {'H','I','D',' ','P','I','C','1','8','F','4','5','5','0','.' }}; ROM struct{BYTE report[HID_RPT01_SIZE];}hid_rpt01={ 0x06, 0xA0, 0xFF, // Usage page (vendor defined) 0x09, 0x01, // Usage ID (vendor defined) 0xA1, 0x01, // Collection (application) // The Input report 0x09, 0x03, // Usage ID - vendor defined 0x15, 0x00, // Logical Minimum (0) 0x26, 0xFF, 0x00, // Logical Maximum (255) 0x75, 0x08, // Report Size (8 bits) 0x95, 0x08, // Report Count (8 fields) 0x81, 0x02, // Input (Data, Variable, Absolute) // The Output report 0x09, 0x04, // Usage ID - vendor defined 0x15, 0x00, // Logical Minimum (0) 0x26, 0xFF, 0x00, // Logical Maximum (255) 0x75, 0x08, // Report Size (8 bits) 0x95, 0x01, // Report Count (2 fields) 0x91, 0x02, // Output (Data, Variable, Absolute) // The Feature report 0x09, 0x05, // Usage ID - vendor defined 0x15, 0x00, // Logical Minimum (0) 0x26, 0xFF, 0x00, // Logical Maximum (255) 0x75, 0x08, // Report Size (8 bits) 0x95, 0x02, // Report Count (2 fields) 0xB1, 0x02, // Feature (Data, Variable, Absolute) 0xC0}; // end collection //Array of congiruation descriptors ROM BYTE *ROM USB_CD_Ptr[]= { (ROM BYTE *ROM)&configDescriptor1 }; //Array of string descriptors ROM BYTE *ROM USB_SD_Ptr[]= { (ROM BYTE *ROM)&sd000, (ROM BYTE *ROM)&sd001, (ROM BYTE *ROM)&sd002 }; #endif
3. usb_device.c (C:\HID_ku\Source) /********************************************************************* FileName: usb_device.c (c) Microhip Corp. /** INCLUDES *******************************************************/ #include "header/GenericTypeDefs.h" #include "header/Compiler.h" #include "header/usb_config.h" #include "header/USB.h" #include "header/usb_device.h" #include "header/HardwareProfile.h" /** VARIABLES ******************************************************/ #pragma udata USB_VOLATILE BYTE USBDeviceState; USB_VOLATILE BYTE USBActiveConfiguration; USB_VOLATILE BYTE USBAlternateInterface[MAX_NUM_INT];
Komunitas eLearning IlmuKomputer.Com Copyright © 2003-2007 IlmuKomputer.Com
92
volatile BDT_ENTRY *pBDTEntryEP0OutCurrent; volatile BDT_ENTRY *pBDTEntryEP0OutNext; volatile BDT_ENTRY *pBDTEntryOut[USB_MAX_EP_NUMBER+1]; volatile BDT_ENTRY *pBDTEntryIn[USB_MAX_EP_NUMBER+1]; USB_VOLATILE BYTE shortPacketStatus; USB_VOLATILE BYTE controlTransferState; USB_VOLATILE PIPE inPipes[1]; USB_VOLATILE BYTE *pDst; USB_VOLATILE BOOL RemoteWakeup; USB_VOLATILE BYTE USTATcopy; USB_VOLATILE WORD USBInMaxPacketSize[USB_MAX_EP_NUMBER]; USB_VOLATILE BYTE *USBInData[USB_MAX_EP_NUMBER]; /** USB FIXED LOCATION VARIABLES ***********************************/ #if defined(__18CXX) #pragma udata USB_BDT=0x400 //See Linker Script,usb4:0x400-0x4FF(256-byte) #endif /******************************************************************** * Section A: Buffer Descriptor Table * - 0x400 - 0x4FF(max) * - MAX_EP_NUMBER is defined in usbcfg.h * - BDT data type is defined in usbd.h *******************************************************************/ #if (USB_PING_PONG_MODE == USB_PING_PONG__NO_PING_PONG) volatile BDT_ENTRY BDT[(USB_MAX_EP_NUMBER + 1) * 2] __attribute__ ((aligned (512))); #elif (USB_PING_PONG_MODE == USB_PING_PONG__EP0_OUT_ONLY) volatile BDT_ENTRY BDT[((USB_MAX_EP_NUMBER + 1) * 2)+1] __attribute__ ((aligned (512))); #elif (USB_PING_PONG_MODE == USB_PING_PONG__FULL_PING_PONG) volatile BDT_ENTRY BDT[(USB_MAX_EP_NUMBER + 1) * 4] __attribute__ ((aligned (512))); #elif (USB_PING_PONG_MODE == USB_PING_PONG__ALL_BUT_EP0) volatile BDT_ENTRY BDT[((USB_MAX_EP_NUMBER + 1) * 4)-2] __attribute__ ((aligned (512))); #else #error "No ping pong mode defined." #endif /******************************************************************** * Section B: EP0 Buffer Space *******************************************************************/ volatile CTRL_TRF_SETUP SetupPkt; // 8-byte only volatile BYTE CtrlTrfData[EP0_BUFF_SIZE]; /******************************************************************** * Section C: non-EP0 Buffer Space *******************************************************************/ // Can provide compile time option to do software pingpong #if defined(USB_USE_HID) volatile unsigned char hid_report_out[HID_INT_OUT_EP_SIZE]; volatile unsigned char hid_report_in[HID_INT_IN_EP_SIZE]; volatile unsigned char hid_report_feature[EP0_BUFF_SIZE]; #endif #if defined(USB_USE_MSD) //volatile far USB_MSD_CBW_CSW msd_cbw_csw; volatile USB_MSD_CBW msd_cbw; volatile USB_MSD_CSW msd_csw; //#pragma udata #if defined(__18CXX) #pragma udata myMSD=0x600 #endif volatile char msd_buffer[512]; #endif #if defined(__18CXX) #pragma udata #endif
Komunitas eLearning IlmuKomputer.Com Copyright © 2003-2007 IlmuKomputer.Com
93
/** DECLARATIONS ***************************************************/ #pragma code // Function: void USBDeviceInit(void) void USBDeviceInit(void) { BYTE i; // Clear all USB error flags USBClearInterruptRegister(U1EIR); // Clears all USB interrupts USBClearInterruptRegister(U1IR); U1EIE = 0x9F; // Unmask all USB error interrupts U1IE = 0xFB; // Enable all interrupts except ACTVIE //power up the module USBPowerModule(); //set the address of the BDT (if applicable) USBSetBDTAddress(BDT); // Reset all of the Ping Pong buffers USBPingPongBufferReset = 1; USBPingPongBufferReset = 0; // Reset to default address U1ADDR = 0x00; //Clear all of the endpoint control registers memset((void*)&U1EP1,0x00,15); //Clear all of the BDT entries for(i=0;i<(sizeof(BDT)/sizeof(BDT_ENTRY));i++) { BDT[i].Val = 0x00; } // Initialize EP0 as a Ctrl EP U1EP0 = EP_CTRL|USB_HANDSHAKE_ENABLED; // Flush any pending transactions while(USBTransactionCompleteIF == 1) { USBClearInterruptFlag(USBTransactionCompleteIFReg,USBTransactionCompleteIFBitNum); } //clear all of the internal pipe information for(i=0;i<(USB_MAX_EP_NUMBER + 1);i++) { inPipes[0].info.Val = 0; } // Make sure packet processing is enabled USBPacketDisable = 0; //Get ready for the first packet pBDTEntryIn[0] = (volatile BDT_ENTRY*)&BDT[EP0_IN_EVEN]; // Clear active configuration USBActiveConfiguration = 0; //Indicate that we are now in the detached state USBDeviceState = DETACHED_STATE; } // Function: void USBTasks(void) void USBDeviceTasks(void) { BYTE i; //If we aren't attached to the bus if(USB_BUS_SENSE != 1) { // Disable module & detach from bus U1CON = 0; // Mask all USB interrupts U1IE = 0; USBDeviceState = DETACHED_STATE; return;
Komunitas eLearning IlmuKomputer.Com Copyright © 2003-2007 IlmuKomputer.Com
94
} //if we are in the detached state if(USBDeviceState == DETACHED_STATE) { U1CON = 0; // Disable module & detach from bus U1IE = 0; while(!U1CONbits.USBEN){U1CONbits.USBEN = 1;} USBDeviceState = ATTACHED_STATE; U1CNFG1 = UCFG_VAL; //UCFG_VAL defined in usb_config.h } if(USBDeviceState == ATTACHED_STATE) { if(!USBSE0Event) { USBClearInterruptRegister(U1IR);// Clear all USB interrupts U1IE=0; // Mask all USB interrupts USBResetIE = 1; // Unmask RESET interrupt USBIdleIE = 1; // Unmask IDLE interrupt USBDeviceState = POWERED_STATE; } } if(USBActivityIF && USBActivityIE) { USBWakeFromSuspend(); } if(USBSuspendControl==1) { return; } if(USBResetIF && USBResetIE) { USBDeviceInit(); USBDeviceState = DEFAULT_STATE; BDT[EP0_OUT_EVEN].ADR = (BYTE*)&SetupPkt; BDT[EP0_OUT_EVEN].CNT = EP0_BUFF_SIZE; BDT[EP0_OUT_EVEN].STAT.Val &= ~_STAT_MASK; BDT[EP0_OUT_EVEN].STAT.Val |= _USIE|_DAT0|_DTSEN|_BSTALL; } if(USBIdleIF && USBIdleIE) { USBSuspend(); } if(USBSOFIF && USBSOFIE) { USBCB_SOF_Handler(); // Required callback, see usbcallbacks.c USBClearInterruptFlag(USBSOFIFReg,USBSOFIFBitNum); } if(USBStallIF && USBStallIE) { USBStallHandler(); } if(USBErrorIF && USBErrorIE) { USBCBErrorHandler(); // Required callback, see usbcallbacks.c USBClearInterruptRegister(U1EIR); // This clears UERRIF }
Komunitas eLearning IlmuKomputer.Com Copyright © 2003-2007 IlmuKomputer.Com
95
if(USBDeviceState < DEFAULT_STATE) return; if(USBTransactionCompleteIE) { for(i = 0; i < 4; i++) { if(USBTransactionCompleteIF) { USTATcopy = U1STAT; USBClearInterruptFlag(USBTransactionCompleteIFReg,USBTransactionCompleteIFBitNum); USBCtrlEPService(); } else break; //USTAT FIFO must be empty. } //end for() } //end if(USBTransactionCompleteIE) } //end of USBDeviceTasks() // Function: void USBStallHandler(void) void USBStallHandler(void) { if(U1EP0bits.EPSTALL == 1) { if((pBDTEntryEP0OutCurrent->STAT.Val == _USIE) && (pBDTEntryIn[0]->STAT.Val == (_USIE|_BSTALL))) { pBDTEntryEP0OutCurrent->STAT.Val = _USIE|_DAT0|_DTSEN|_BSTALL; } //end if U1EP0bits.EPSTALL = 0; // Clear stall status } //end if USBClearInterruptFlag(USBSOFIFReg,USBSOFIFBitNum); } // Function: void USBSuspend(void) void USBSuspend(void) { USBActivityIE = 1; // Enable bus activity interrupt USBClearInterruptFlag(USBIdleIFReg,USBIdleIFBitNum); #if defined(__18CXX) U1CONbits.SUSPND = 1; // Put USB module in power conserve #endif USBCBSuspend(); // Required callback, see usbcallbacks.c } //Function: void USBWakeFromSuspend(void) void USBWakeFromSuspend(void) { #if defined(__18CXX) U1CONbits.SUSPND = 0; // Bring USB module out of power conserve #endif USBCBWakeFromSuspend(); // Required callback, see usbcallbacks.c USBActivityIE = 0; #if defined(__18CXX) while(USBActivityIF) #endif { USBClearInterruptFlag(USBActivityIFReg,USBActivityIFBitNum); } // Added } //end USBWakeFromSuspend // Function:
void USBCtrlEPService(void)
Komunitas eLearning IlmuKomputer.Com Copyright © 2003-2007 IlmuKomputer.Com
96
void USBCtrlEPService(void) { if((USTATcopy & USTAT_EP0_PP_MASK) == USTAT_EP0_OUT_EVEN) { #if defined(__18CXX) pBDTEntryEP0OutCurrent = (volatile BDT_ENTRY*)&BDT[(USTATcopy & USTAT_EP_MASK)>>1]; #elif defined(__C30__) pBDTEntryEP0OutCurrent = (volatile BDT_ENTRY*)&BDT[(USTATcopy & USTAT_EP_MASK)>>2]; #else #error "unimplemented" #endif pBDTEntryEP0OutNext = pBDTEntryEP0OutCurrent; //Toggle it to the next ping pong buffer (if applicable) ((BYTE_VAL*)&pBDTEntryEP0OutNext)->Val ^= USB_NEXT_EP0_OUT_PING_PONG; if(pBDTEntryEP0OutCurrent->STAT.PID == SETUP_TOKEN) { USBCtrlTrfSetupHandler(); } else { USBCtrlTrfOutHandler(); } } else if((USTATcopy & USTAT_EP0_PP_MASK) == USTAT_EP0_IN) // EP0 IN { USBCtrlTrfInHandler(); } }//end USBCtrlEPService // Function: void USBCtrlTrfSetupHandler(void) void USBCtrlTrfSetupHandler(void) { //if the SIE currently owns the buffer if(pBDTEntryIn[0]->STAT.UOWN != 0) { //give control back to the CPU pBDTEntryIn[0]->STAT.Val = _UCPU; } //Keep track of if a short packet has been sent yet or not shortPacketStatus = SHORT_PKT_NOT_USED; /* Stage 1 */ controlTransferState = WAIT_SETUP; inPipes[0].wCount.Val = 0; inPipes[0].info.Val = 0; /* Stage 2 */ USBCheckStdRequest(); USBCBCheckOtherReq(); // Required callback, see usbcallbacks.c /* Stage 3 */ USBCtrlEPServiceComplete(); }//end USBCtrlTrfSetupHandler // Function: void USBCtrlTrfOutHandler(void) void USBCtrlTrfOutHandler(void) { if(controlTransferState == CTRL_TRF_RX) { USBCtrlTrfRxService(); if (SetupPkt.bmRequestType == (USB_SETUP_HOST_TO_DEVICE | USB_SETUP_TYPE_CLASS | USB_SETUP_RECIPIENT_INTERFACE)) {
Komunitas eLearning IlmuKomputer.Com Copyright © 2003-2007 IlmuKomputer.Com
97
HandleControlOutReport(); } if(pBDTEntryEP0OutCurrent->STAT.DTS == 0) { pBDTEntryEP0OutNext->STAT.Val = _USIE|_DAT1|_DTSEN; } else { pBDTEntryEP0OutNext->STAT.Val = _USIE|_DAT0|_DTSEN; } } else {
// CTRL_TRF_TX USBPrepareForNextSetupTrf();
} } // Function: void USBCtrlTrfInHandler(void) void USBCtrlTrfInHandler(void) { BYTE lastDTS; lastDTS = pBDTEntryIn[0]->STAT.DTS; ((BYTE_VAL*)&pBDTEntryIn[0])->Val ^= USB_NEXT_EP0_IN_PING_PONG; if(USBDeviceState == ADR_PENDING_STATE) { U1ADDR = SetupPkt.bDevADR.Val; if(U1ADDR > 0) { USBDeviceState=ADDRESS_STATE; } else { USBDeviceState=DEFAULT_STATE; } } //end if if(controlTransferState == CTRL_TRF_TX) { pBDTEntryIn[0]->ADR = (BYTE *)CtrlTrfData; USBCtrlTrfTxService(); if(shortPacketStatus == SHORT_PKT_SENT) { pBDTEntryIn[0]->STAT.Val = _USIE|_BSTALL; } else { if(lastDTS == 0) { pBDTEntryIn[0]->STAT.Val = _USIE|_DAT1|_DTSEN; } else { pBDTEntryIn[0]->STAT.Val = _USIE|_DAT0|_DTSEN; } } //end if(....)else } else // CTRL_TRF_RX { USBPrepareForNextSetupTrf(); } } // Function: void USBPrepareForNextSetupTrf(void) void USBPrepareForNextSetupTrf(void) {
Komunitas eLearning IlmuKomputer.Com Copyright © 2003-2007 IlmuKomputer.Com
98
if((controlTransferState == CTRL_TRF_RX) && (USBPacketDisable == 1) && (pBDTEntryEP0OutCurrent->CNT == sizeof(CTRL_TRF_SETUP)) && (pBDTEntryEP0OutCurrent->STAT.PID == SETUP_TOKEN) && (pBDTEntryEP0OutNext->STAT.UOWN == 0)) { unsigned char setup_cnt; pBDTEntryEP0OutNext->ADR = (BYTE*)&SetupPkt; for(setup_cnt = 0; setup_cnt < sizeof(CTRL_TRF_SETUP); setup_cnt++) { *(((BYTE*)&SetupPkt)+setup_cnt) = *(((BYTE*)&CtrlTrfData)+setup_cnt); }//end for } else { controlTransferState = WAIT_SETUP; pBDTEntryEP0OutNext->CNT = EP0_BUFF_SIZE; // Defined in usbcfg.h pBDTEntryEP0OutNext->ADR = (BYTE*)&SetupPkt; pBDTEntryEP0OutNext->STAT.Val = _USIE|_DAT0|_DTSEN|_BSTALL; //Added #F1 pBDTEntryIn[0]->STAT.Val = _UCPU; { BDT_ENTRY* p; p = (BDT_ENTRY*)(((unsigned int)pBDTEntryIn[0])^USB_NEXT_EP0_IN_PING_PONG); p->STAT.Val = _UCPU; } } }
//end USBPrepareForNextSetupTrf
// Function: void USBCheckStdRequest(void) void USBCheckStdRequest(void) { if(SetupPkt.RequestType != STANDARD) return; switch(SetupPkt.bRequest) { case SET_ADR: inPipes[0].info.bits.busy = 1; // This will generate a zero length packet USBDeviceState = ADR_PENDING_STATE; // Update state only break; case GET_DSC: USBStdGetDscHandler(); break; case SET_CFG: USBStdSetCfgHandler(); break; case GET_CFG: inPipes[0].pSrc.bRam = (BYTE*)&USBActiveConfiguration; // Set Source inPipes[0].info.bits.ctrl_trf_mem = _RAM; // Set memory type inPipes[0].wCount.v[0] = 1; // Set data count inPipes[0].info.bits.busy = 1; break; case GET_STATUS: USBStdGetStatusHandler(); break; case CLR_FEATURE: case SET_FEATURE: USBStdFeatureReqHandler(); break; case GET_INTF: inPipes[0].pSrc.bRam = (BYTE*)&USBAlternateInterface+SetupPkt.bIntfID; // Set source inPipes[0].info.bits.ctrl_trf_mem = _RAM; // Set memory type inPipes[0].wCount.v[0] = 1; // Set data count inPipes[0].info.bits.busy = 1; break;
Komunitas eLearning IlmuKomputer.Com Copyright © 2003-2007 IlmuKomputer.Com
99
} }
case SET_INTF: inPipes[0].info.bits.busy = 1; USBAlternateInterface[SetupPkt.bIntfID] = SetupPkt.bAltID; break; case SET_DSC: USBCBStdSetDscHandler(); break; case SYNCH_FRAME: default: break; //end switch //end USBCheckStdRequest
// Function: void USBStdFeatureReqHandler(void) void USBStdFeatureReqHandler(void) { BDT_ENTRY *p; unsigned int* pUEP; if((SetupPkt.bFeature == DEVICE_REMOTE_WAKEUP)&& (SetupPkt.Recipient == RCPT_DEV)) { inPipes[0].info.bits.busy = 1; if(SetupPkt.bRequest == SET_FEATURE) RemoteWakeup = TRUE; else RemoteWakeup = FALSE; }//end if if((SetupPkt.bFeature == ENDPOINT_HALT)&& (SetupPkt.Recipient == RCPT_EP)&& (SetupPkt.EPNum != 0)) { BYTE i; inPipes[0].info.bits.busy = 1;//loop for each of the possible ping-pong buffers for(i=0; i<2; i++) { //point to the first EP0 OUT ping pong buffer p = (BDT_ENTRY*)&BDT[EP0_OUT_EVEN]; //jump from this endpoint to the requested endpoint p += EP(SetupPkt.EPNum,SetupPkt.EPDir,i); //if it was a SET_FEATURE request if(SetupPkt.bRequest == SET_FEATURE) { //Then STALL the endpoint p->STAT.Val = _USIE|_BSTALL; } else { pUEP = (unsigned int*)(&U1EP0+SetupPkt.EPNum); *pUEP &= ~UEP_STALL; if(SetupPkt.EPDir == 1) // IN { p->STAT.Val = _UCPU|_DAT1; } else { p->STAT.Val = _USIE|_DAT1|_DTSEN; } } //end if } } }
//end if //end USBStdFeatureReqHandler
// Function:
void USBStdGetDscHandler(void)
Komunitas eLearning IlmuKomputer.Com Copyright © 2003-2007 IlmuKomputer.Com
100
void USBStdGetDscHandler(void) { if(SetupPkt.bmRequestType == 0x80) { inPipes[0].info.Val = USB_INPIPES_ROM | USB_INPIPES_BUSY | USB_INPIPES_INCLUDE_ZERO; switch(SetupPkt.bDescriptorType) { case USB_DESCRIPTOR_DEVICE: inPipes[0].pSrc.bRom = (ROM BYTE*)&device_dsc; inPipes[0].wCount.Val = sizeof(device_dsc); break; case USB_DESCRIPTOR_CONFIGURATION: inPipes[0].pSrc.bRom = *(USB_CD_Ptr+SetupPkt.bDscIndex); inPipes[0].wCount.Val = *(inPipes[0].pSrc.wRom+1); // Set data count break; case USB_DESCRIPTOR_STRING: inPipes[0].pSrc.bRom = *(USB_SD_Ptr+SetupPkt.bDscIndex); inPipes[0].wCount.Val = *inPipes[0].pSrc.bRom; // Set data count break; default: inPipes[0].info.Val = 0; break; } //end switch } //end if } //end USBStdGetDscHandler // Function: void USBStdGetStatusHandler(void) void USBStdGetStatusHandler(void) { CtrlTrfData[0] = 0; // Initialize content CtrlTrfData[1] = 0; switch(SetupPkt.Recipient) { case RCPT_DEV: inPipes[0].info.bits.busy = 1; if(self_power == 1) // self_power is defined in HardwareProfile.h { CtrlTrfData[0]|=0x01; } if(RemoteWakeup == TRUE) { CtrlTrfData[0]|=0x02; } break; case RCPT_INTF: inPipes[0].info.bits.busy = 1; // No data to update break; case RCPT_EP: inPipes[0].info.bits.busy = 1; { BDT_ENTRY *p; p = (BDT_ENTRY*)&BDT[EP0_OUT_EVEN]; p += EP(SetupPkt.EPNum,SetupPkt.EPDir,0); if(p->STAT.Val & _BSTALL) // Use _BSTALL as a bit mask CtrlTrfData[0]=0x01; // Set bit0 break; } } //end switch if(inPipes[0].info.bits.busy == 1) { inPipes[0].pSrc.bRam = (BYTE*)&CtrlTrfData; // Set Source inPipes[0].info.bits.ctrl_trf_mem = _RAM; // Set memory type inPipes[0].wCount.v[0] = 2; // Set data count
Komunitas eLearning IlmuKomputer.Com Copyright © 2003-2007 IlmuKomputer.Com
101
} }
//end if(....) //end USBStdGetStatusHandler
// Function: void USBCtrlEPServiceComplete(void) void USBCtrlEPServiceComplete(void) { USBPacketDisable = 0; if(inPipes[0].info.bits.busy == 0) { pBDTEntryEP0OutNext->CNT = EP0_BUFF_SIZE; pBDTEntryEP0OutNext->ADR = (BYTE*)&SetupPkt; pBDTEntryEP0OutNext->STAT.Val = _USIE|_DAT0|_DTSEN|_BSTALL; pBDTEntryIn[0]->STAT.Val = _USIE|_BSTALL; } else // A module has claimed ownership of the control transfer session. { if(SetupPkt.DataDir == DEV_TO_HOST) { if(SetupPkt.wLength < inPipes[0].wCount.Val) { inPipes[0].wCount.Val = SetupPkt.wLength; } USBCtrlTrfTxService(); controlTransferState = CTRL_TRF_TX; pBDTEntryEP0OutNext->CNT = EP0_BUFF_SIZE; pBDTEntryEP0OutNext->ADR = (BYTE*)&SetupPkt; pBDTEntryEP0OutNext->STAT.Val = _USIE; // Note: DTSEN is 0! pBDTEntryEP0OutCurrent->CNT = EP0_BUFF_SIZE; pBDTEntryEP0OutCurrent->ADR = (BYTE*)&SetupPkt; pBDTEntryEP0OutCurrent->STAT.Val = _USIE; // Note: DTSEN is 0! pBDTEntryIn[0]->ADR = (BYTE*)&CtrlTrfData; pBDTEntryIn[0]->STAT.Val = _USIE|_DAT1|_DTSEN; } else // (SetupPkt.DataDir == HOST_TO_DEV) { controlTransferState = CTRL_TRF_RX; pBDTEntryIn[0]->CNT = 0; pBDTEntryIn[0]->STAT.Val = _USIE|_DAT1|_DTSEN; pBDTEntryEP0OutNext->CNT = EP0_BUFF_SIZE; pBDTEntryEP0OutNext->ADR = (BYTE*)&CtrlTrfData; pBDTEntryEP0OutNext->STAT.Val = _USIE|_DAT1|_DTSEN; } //end if(SetupPkt.DataDir == DEV_TO_HOST) } //end if(ctrl_trf_session_owner == MUID_NULL) } //end USBCtrlEPServiceComplete // Function: void USBCtrlTrfTxService(void) void USBCtrlTrfTxService(void) { WORD_VAL byteToSend; if(inPipes[0].wCount.Val < EP0_BUFF_SIZE) { byteToSend.Val = inPipes[0].wCount.Val; if(shortPacketStatus == SHORT_PKT_NOT_USED) { shortPacketStatus = SHORT_PKT_PENDING; } else if(shortPacketStatus == SHORT_PKT_PENDING) { shortPacketStatus = SHORT_PKT_SENT; } //end if /* end v2b fix for this section */ } else
Komunitas eLearning IlmuKomputer.Com Copyright © 2003-2007 IlmuKomputer.Com
102
{ byteToSend.Val = EP0_BUFF_SIZE; } #if defined(__18CXX) pBDTEntryIn[0]->STAT.BC9 = 0; pBDTEntryIn[0]->STAT.BC8 = 0; #endif pBDTEntryIn[0]->STAT.Val |= byteToSend.byte.HB; pBDTEntryIn[0]->CNT = byteToSend.byte.LB; inPipes[0].wCount.Val = inPipes[0].wCount.Val - byteToSend.Val; pDst = (BYTE*)CtrlTrfData; // Set destination pointer if(inPipes[0].info.bits.ctrl_trf_mem == USB_INPIPES_ROM) // Determine type of memory source { while(byteToSend.Val) { *pDst++ = *inPipes[0].pSrc.bRom++; byteToSend.Val--; } //end while(byte_to_send.Val) } else // RAM { while(byteToSend.Val) { *pDst++ = *inPipes[0].pSrc.bRam++; byteToSend.Val--; } //end while(byte_to_send.Val) } //end if(usb_stat.ctrl_trf_mem == _ROM) } //end USBCtrlTrfTxService // Function: void USBCtrlTrfRxService(void) void USBCtrlTrfRxService(void) { WORD_VAL byteToRead; byteToRead.byte.HB = 0x03 & pBDTEntryEP0OutNext->STAT.Val; // Filter out last 2 bits byteToRead.byte.LB = pBDTEntryEP0OutNext->CNT; inPipes[0].wCount.Val = inPipes[0].wCount.Val + byteToRead.Val; inPipes[0].pSrc.bRam = (BYTE*)&CtrlTrfData; while(byteToRead.Val) { *pDst++ = *inPipes[0].pSrc.bRam++; byteToRead.Val--; } //end while(byteToRead.Val) } //end USBCtrlTrfRxService // Function: void USBStdSetCfgHandler(void) void USBStdSetCfgHandler(void) { inPipes[0].info.bits.busy = 1; memset((void*)&U1EP1,0x00,15); memset((void*)&USBAlternateInterface,0x00,MAX_NUM_INT); USBActiveConfiguration = SetupPkt.bConfigurationValue; if(SetupPkt.bConfigurationValue == 0) { USBDeviceState = ADDRESS_STATE; } else { USBDeviceState = CONFIGURED_STATE; USBInitEP((BYTE ROM*)(USB_CD_Ptr[USBActiveConfiguration-1])); USBCBInitEP(); } //end if(SetupPkt.bConfigurationValue == 0) } //end USBStdSetCfgHandler
Komunitas eLearning IlmuKomputer.Com Copyright © 2003-2007 IlmuKomputer.Com
103
// Function: void USBConfigureEndpoint(BYTE EPNum, BYTE direction) void USBConfigureEndpoint(BYTE EPNum, BYTE direction) { volatile BDT_ENTRY* handle; handle = (volatile BDT_ENTRY*)&BDT[EP0_OUT_EVEN]; handle += BD(EPNum,direction,0)/sizeof(BDT_ENTRY); handle->STAT.UOWN = 0; if(direction == 0) { pBDTEntryOut[EPNum] = handle; } else { pBDTEntryIn[EPNum] = handle; } #if (USB_PING_PONG_MODE == USB_PING_PONG__FULL_PING_PONG) handle->STAT.DTS = 0; (handle+1)->STAT.DTS = 1; #elif (USB_PING_PONG_MODE == USB_PING_PONG__NO_PING_PONG) handle->STAT.DTS = 1; #elif (USB_PING_PONG_MODE == USB_PING_PONG__EP0_OUT_ONLY) if(EPNum != 0) { handle->STAT.DTS = 1; } #elif (USB_PING_PONG_MODE == USB_PING_PONG__ALL_BUT_EP0) if(EPNum != 0) { handle->STAT.DTS = 0; (handle+1)->STAT.DTS = 1; } #endif } /******************************************************************** * Function: void USBEnableEndpoint(BYTE ep, BYTE options) *******************************************************************/ void USBEnableEndpoint(BYTE ep, BYTE options) { { unsigned int* p; p = (unsigned int*)(&U1EP0+ep); *p = options; } if(options & USB_OUT_ENABLED) { USBConfigureEndpoint(ep,0); } if(options & USB_IN_ENABLED) { USBConfigureEndpoint(ep,1); } } // Function: void USBStallEndpoint(BYTE ep, BYTE dir) void USBStallEndpoint(BYTE ep, BYTE dir) { BDT_ENTRY *p; p = (BDT_ENTRY*)(&BDT[EP(ep,dir,0)]); p->STAT.Val |= _BSTALL | _USIE; #if (USB_PING_PONG_MODE == USB_PING_PONG__FULL_PING_PONG) || \ (USB_PING_PONG_MODE == USB_PING_PONG__ALL_BUT_EP0) p = (BDT_ENTRY*)(&BDT[EP(ep,dir,1)]);
Komunitas eLearning IlmuKomputer.Com Copyright © 2003-2007 IlmuKomputer.Com
104
p->STAT.Val |= _BSTALL | _USIE; #endif } // Function: USB_HANDLE USBTransferOnePacket() USB_HANDLE USBTransferOnePacket(BYTE ep,BYTE dir,BYTE* data,BYTE len) { USB_HANDLE handle; //If the direction is IN if(dir != 0) { handle = pBDTEntryIn[ep]; } else { handle = pBDTEntryOut[ep]; } #if (USB_PING_PONG_MODE == USB_PING_PONG__NO_PING_PONG) handle->STAT.Val ^= _DTSMASK; #elif (USB_PING_PONG_MODE == USB_PING_PONG__EP0_OUT_ONLY) if(ep != 0) { handle->STAT.Val ^= _DTSMASK; } #endif handle->ADR = data; handle->CNT = len; handle->STAT.Val &= _DTSMASK; handle->STAT.Val |= _USIE | _DTSEN; if(dir != 0) { ((BYTE_VAL*)&pBDTEntryIn[ep])->Val ^= USB_NEXT_PING_PONG; } else { ((BYTE_VAL*)&pBDTEntryOut[ep])->Val ^= USB_NEXT_PING_PONG; } return handle; } // Function: void USBClearInterruptFlag(BYTE* reg, BYTE flag) void USBClearInterruptFlag(BYTE* reg, BYTE flag) { #if defined(__18CXX) *reg &= ~(0x01<
4. usb_function_hid.c (C:\HID_ku\Source) /******************************************************************** FileName: usb_function_hid.c (c)Microchip Technology, Inc. Change History: 2.1 02/26/2007 Updated for simplicity and to use common coding style *******************************************************************/ /** INCLUDES *******************************************************/ #include "header/GenericTypeDefs.h" #include "header/Compiler.h"
Komunitas eLearning IlmuKomputer.Com Copyright © 2003-2007 IlmuKomputer.Com
105
#include "header/usb_config.h" #include "header/usb_device.h" #include "header/usb_function_hid.h" /** VARIABLES ******************************************************/ #pragma udata BYTE idle_rate; BYTE active_protocol; // [0] Boot Protocol [1] Report Protocol BYTE hid_rpt_rx_len; /** PRIVATE PROTOTYPES *********************************************/ void HIDGetReportHandler(void); void HIDSetReportHandler(void); /** DECLARATIONS ***************************************************/ #pragma code //CLASS SPECIFIC REQUESTS ****************************************/ // Function: void USBCheckHIDRequest(void) // This routine checks the setup data packet to see void USBCheckHIDRequest(void) { if(SetupPkt.Recipient != RCPT_INTF) return; if(SetupPkt.bIntfID != HID_INTF_ID) return; if(SetupPkt.bRequest == GET_DSC) { switch(SetupPkt.bDescriptorType) { case DSC_HID: if(USBActiveConfiguration == 1) { USBEP0SendROMPtr( (ROM BYTE*)&configDescriptor1 + 18, sizeof(USB_HID_DSC)+3, // RRoj hack USB_EP0_INCLUDE_ZERO); } break; case DSC_RPT: if(USBActiveConfiguration == 1) { USBEP0SendROMPtr( (ROM BYTE*)&hid_rpt01, sizeof(hid_rpt01), //See usbcfg.h USB_EP0_INCLUDE_ZERO); } break; case DSC_PHY: USBEP0Transmit(USB_EP0_NO_DATA); break; } //end switch(SetupPkt.bDescriptorType) } //end if(SetupPkt.bRequest == GET_DSC) if(SetupPkt.RequestType != CLASS) return; switch(SetupPkt.bRequest) { case GET_REPORT: HIDGetReportHandler(); break; case SET_REPORT: HIDSetReportHandler(); break; case GET_IDLE: USBEP0SendRAMPtr( (BYTE*)&idle_rate, 1,
Komunitas eLearning IlmuKomputer.Com Copyright © 2003-2007 IlmuKomputer.Com
106
} }
USB_EP0_INCLUDE_ZERO); break; case SET_IDLE: USBEP0Transmit(USB_EP0_NO_DATA); idle_rate = SetupPkt.W_Value.byte.HB; break; case GET_PROTOCOL: USBEP0SendRAMPtr( (BYTE*)&active_protocol, 1, USB_EP0_NO_OPTIONS); break; case SET_PROTOCOL: USBEP0Transmit(USB_EP0_NO_DATA); active_protocol = SetupPkt.W_Value.byte.LB; break; //end switch(SetupPkt.bRequest) //end USBCheckHIDRequest
// Function: void HIDGetReportHandler(void) void HIDGetReportHandler(void) { inPipes[0].info.bits.busy = 1; inPipes[0].info.Val = USB_INPIPES_RAM | USB_INPIPES_BUSY | USB_INPIPES_INCLUDE_ZERO; if ((SetupPkt.W_Value.byte.HB) == 0x01) { // Input report if (SetupPkt.W_Value.byte.LB == 0x00) { // Report ID = 0 inPipes[0].pSrc.bRam = (BYTE*)&hid_report_in; inPipes[0].wCount.Val = HID_INPUT_REPORT_BYTES; } else { // Stall unsupported report IDs. pBDTEntryIn[0]->STAT.Val = _USIE|_BSTALL; } } else if (SetupPkt.W_Value.byte.HB == 0x03) { // Feature report if (SetupPkt.W_Value.byte.LB == 0x00) { // Report ID = 0 inPipes[0].pSrc.bRam = (BYTE*)&hid_report_feature; inPipes[0].wCount.Val = HID_FEATURE_REPORT_BYTES; } else { // Stall unsupported report IDs. pBDTEntryIn[0]->STAT.Val = _USIE|_BSTALL; } } else { // Stall unsupported report types. pBDTEntryIn[0]->STAT.Val = _USIE|_BSTALL; } } //end HIDGetReportHandler // Function: void HIDSetReportHandler(void) void HIDSetReportHandler(void)
Komunitas eLearning IlmuKomputer.Com Copyright © 2003-2007 IlmuKomputer.Com
107
{
}
if (ReportSupported()) { inPipes[0].info.bits.busy = 1; } else { // The endpoint will return STALL. inPipes[0].info.bits.busy = 0; } //end HIDSetReportHandler
//******** USER API********************************************** // Function: void HIDInitEP(void) *******************************************************************/ #if !defined(USB_DYNAMIC_EP_CONFIG) void HIDInitEP(void) { }//end HIDInitEP #endif /** EOF hid.c ******************************************************/
5. Compiler.h (C:\HID_ku\Header) /********************************************************************* FileName: Compiler.h (c) Microchip Technology, Inc. ********************************************************************/ #ifndef __COMPILER_H #define __COMPILER_H // Include proper device header file #if defined(__18CXX) || defined(HI_TECH_C) // All PIC18 processors #if defined(HI_TECH_C) // HI TECH PICC-18 compiler #define __18CXX #include #else // Microchip C18 compiler #include #endif #elif defined(__PIC24F__) // Microchip C30 compiler // PIC24F processor #include #elif defined(__PIC24H__) // Microchip C30 compiler // PIC24H processor #include #elif defined(__dsPIC33F__) // Microchip C30 compiler // dsPIC33F processor #include #elif defined(__dsPIC30F__) // Microchip C30 compiler // dsPIC30F processor #include #elif defined(__PIC32MX__) // Microchip C32 compiler #if !defined(__C32__) #define __C32__ #endif #include #include #else #error Unknown processor or compiler. See Compiler.h #endif #include <stdio.h> #include <stdlib.h> #include <string.h>
Komunitas eLearning IlmuKomputer.Com Copyright © 2003-2007 IlmuKomputer.Com
108
// Base RAM pointer type for given architecture #if defined(__C32__) #define PTR_BASE DWORD #else #define PTR_BASE WORD #endif // Definitions that apply to all compilers, except C18 #if !defined(__18CXX) || defined(HI_TECH_C) #define memcmppgm2ram(a,b,c) memcmp(a,b,c) #define strcmppgm2ram(a,b)strcmp(a,b) #define memcpypgm2ram(a,b,c) memcpy(a,b,c) #define strcpypgm2ram(a,b) strcpy(a,b) #define strncpypgm2ram(a,b,c) strncpy(a,b,c) #define strstrrampgm(a,b) strstr(a,b) #define strlenpgm(a) strlen(a) #define strchrpgm(a,b) strchr(a,b) #define strcatpgm2ram(a,b) strcat(a,b) #endif // Definitions that apply to all 8-bit products // (PIC18) #if defined(__18CXX) #define __attribute__(a) // Microchip C18 specific defines #if !defined(HI_TECH_C) #define ROM rom #define strcpypgm2ram(a, b) strcpypgm2ram(a,(far rom char*)b) #endif // HI TECH PICC-18 STD specific defines #if defined(HI_TECH_C) #define ROM const #define rom #define Nop() asm("NOP"); #define ClrWdt() asm("CLRWDT"); #define Reset() asm("RESET"); #endif // Definitions that apply to all 16-bit and 32-bit products // (PIC24F, PIC24H, dsPIC30F, dsPIC33F, and PIC32) #else #define ROM const // 16-bit specific defines (PIC24F, PIC24H, dsPIC30F, dsPIC33F) #if defined(__C30__) #define Reset() asm("reset") #endif // 32-bit specific defines (PIC32) #if defined(__C32__) #define persistent #define far #define Reset() SoftReset() #define ClrWdt() (WDTCONSET = _WDTCON_WDTCLR_MASK) #define Nop() asm("nop") #endif #endif #endif
6. GenericTypeDefs.h (C:\HID_ku\Header) /********************************************************************* FileName: GenericTypeDefs.h ********************************************************************/ #ifndef __GENERIC_TYPE_DEFS_H_
Komunitas eLearning IlmuKomputer.Com Copyright © 2003-2007 IlmuKomputer.Com
109
#define __GENERIC_TYPE_DEFS_H_ typedef enum _BOOL { FALSE = 0, TRUE } BOOL; // Undefined size #ifndef NULL #define NULL 0 //((void *)0) #endif #define PUBLIC // Function attributes #define PROTECTED #define PRIVATE static typedef unsigned char BYTE; // 8-bit unsigned typedef unsigned short int WORD; // 16-bit unsigned typedef unsigned long DWORD; // 32-bit unsigned typedef unsigned long long QWORD; // 64-bit unsigned typedef signed char CHAR; // 8-bit signed typedef signed short int SHORT; // 16-bit signed typedef signed long LONG; // 32-bit signed typedef signed long long LONGLONG; // 64-bit signed /* Alternate definitions */ typedef void VOID; typedef char CHAR8; typedef unsigned char UCHAR8; typedef signed int INT; typedef signed char INT8; typedef signed short int INT16; typedef signed long int INT32; typedef signed long long INT64; typedef unsigned int UINT; typedef unsigned char UINT8; typedef unsigned short int UINT16; typedef unsigned long int UINT32; // other name for 32-bit integer typedef unsigned long long UINT64; typedef union _BYTE_VAL { BYTE Val; struct { unsigned char b0:1; unsigned char b1:1; unsigned char b2:1; unsigned char b3:1; unsigned char b4:1; unsigned char b5:1; unsigned char b6:1; unsigned char b7:1; } bits; } BYTE_VAL, BYTE_BITS; typedef union _WORD_VAL { WORD Val; BYTE v[2]; struct { BYTE LB; BYTE HB; } byte; struct { unsigned char b0:1; unsigned char b1:1; unsigned char b2:1; unsigned char b3:1; unsigned char b4:1; unsigned char b5:1;
Komunitas eLearning IlmuKomputer.Com Copyright © 2003-2007 IlmuKomputer.Com
110
unsigned char b6:1; unsigned char b7:1; unsigned char b8:1; unsigned char b9:1; unsigned char b10:1; unsigned char b11:1; unsigned char b12:1; unsigned char b13:1; unsigned char b14:1; unsigned char b15:1; } bits; } WORD_VAL, WORD_BITS; typedef union _DWORD_VAL { DWORD Val; WORD w[2]; BYTE v[4]; struct { WORD LW; WORD HW; } word; struct { BYTE LB; BYTE HB; BYTE UB; BYTE MB; } byte; struct { WORD_VAL low; WORD_VAL high; }wordUnion; struct { unsigned char b0:1; unsigned char b1:1; unsigned char b2:1; unsigned char b3:1; unsigned char b4:1; unsigned char b5:1; unsigned char b6:1; unsigned char b7:1; unsigned char b8:1; unsigned char b9:1; unsigned char b10:1; unsigned char b11:1; unsigned char b12:1; unsigned char b13:1; unsigned char b14:1; unsigned char b15:1; unsigned char b16:1; unsigned char b17:1; unsigned char b18:1; unsigned char b19:1; unsigned char b20:1; unsigned char b21:1; unsigned char b22:1; unsigned char b23:1; unsigned char b24:1; unsigned char b25:1; unsigned char b26:1; unsigned char b27:1;
Komunitas eLearning IlmuKomputer.Com Copyright © 2003-2007 IlmuKomputer.Com
111
unsigned char b28:1; unsigned char b29:1; unsigned char b30:1; unsigned char b31:1; } bits; } DWORD_VAL; #define LSB(a) #define MSB(a) #define LOWER_LSB(a) #define LOWER_MSB(a) #define UPPER_LSB(a) #define UPPER_MSB(a) typedef union _QWORD_VAL { QWORD Val; DWORD d[2]; WORD w[4]; BYTE v[8]; struct { DWORD LD; DWORD HD; } dword; struct { WORD LW; WORD HW; WORD UW; WORD MW; } word; struct { unsigned char b0:1; unsigned char b1:1; unsigned char b2:1; unsigned char b3:1; unsigned char b4:1; unsigned char b5:1; unsigned char b6:1; unsigned char b7:1; unsigned char b8:1; unsigned char b9:1; unsigned char b10:1; unsigned char b11:1; unsigned char b12:1; unsigned char b13:1; unsigned char b14:1; unsigned char b15:1; unsigned char b16:1; unsigned char b17:1; unsigned char b18:1; unsigned char b19:1; unsigned char b20:1; unsigned char b21:1; unsigned char b22:1; unsigned char b23:1; unsigned char b24:1; unsigned char b25:1; unsigned char b26:1; unsigned char b27:1; unsigned char b28:1; unsigned char b29:1; unsigned char b30:1;
((a).v[0]) ((a).v[1]) ((a).v[0]) ((a).v[1]) ((a).v[2]) ((a).v[3])
Komunitas eLearning IlmuKomputer.Com Copyright © 2003-2007 IlmuKomputer.Com
112
unsigned char b31:1; unsigned char b32:1; unsigned char b33:1; unsigned char b34:1; unsigned char b35:1; unsigned char b36:1; unsigned char b37:1; unsigned char b38:1; unsigned char b39:1; unsigned char b40:1; unsigned char b41:1; unsigned char b42:1; unsigned char b43:1; unsigned char b44:1; unsigned char b45:1; unsigned char b46:1; unsigned char b47:1; unsigned char b48:1; unsigned char b49:1; unsigned char b50:1; unsigned char b51:1; unsigned char b52:1; unsigned char b53:1; unsigned char b54:1; unsigned char b55:1; unsigned char b56:1; unsigned char b57:1; unsigned char b58:1; unsigned char b59:1; unsigned char b60:1; unsigned char b61:1; unsigned char b62:1; unsigned char b63:1; } bits; } QWORD_VAL; #endif //__GENERIC_TYPE_DEFS_H_
7. HardwareProfile.h (C:\HID_ku\Header) /******************************************************************** FileName: HardwareProfile.h (c))Microchip Technology, Inc. ********************************************************************/ #ifndef HARDWARE_PROFILE_H #define HARDWARE_PROFILE_H #if !defined(DEMO_BOARD) #if defined(__C30__) #if defined(__PIC24FJ256GB110__) #define EXPLORER_16 #define DEMO_BOARD EXPLORER_16 #define CLOCK_FREQ 32000000 #endif #endif #if defined(__18CXX) #if defined(__18F4550) #define DEMO_BOARD PICDEM_FS_USB #define PICDEM_FS_USB #define WRITE_BLOCK_SIZE 32 #define ERASE_BLOCK_SIZE 64 #define CLOCK_FREQ 48000000 #elif defined(__18F87J50) || defined(__18F85J50) #define DEMO_BOARD PIC18F87J50_PIM
Komunitas eLearning IlmuKomputer.Com Copyright © 2003-2007 IlmuKomputer.Com
113
#define PIC18F87J50_PIM #define WRITE_BLOCK_SIZE 64 #define ERASE_BLOCK_SIZE 1024 #define CLOCK_FREQ 48000000 #endif #endif #endif #if !defined(DEMO_BOARD) #error "Demo board not defined. Either define DEMO_BOARD for a custom board or select the correct processor for the demo board." #endif #define BAUD_RATE 57600 /** TRIS ***********************************************************/ #define INPUT_PIN 1 #define OUTPUT_PIN 0 /** USB ************************************************************/ #if defined(PICDEM_FS_USB) #define U1ADDR UADDR #define U1IE UIE #define U1IR UIR #define U1EIR UEIR #define U1EIE UEIE #define U1CON UCON #define U1EP0 UEP0 #define U1CONbits UCONbits #define U1EP1 UEP1 #define U1CNFG1 UCFG #define U1STAT USTAT #define U1EP0bits UEP0bits #define tris_usb_bus_sense TRISAbits.TRISA1 // Input #if defined(USE_USB_BUS_SENSE_IO) #define USB_BUS_SENSE PORTAbits.RA1 #else #define USB_BUS_SENSE 1 #endif #define tris_self_power TRISAbits.TRISA2 #if defined(USE_SELF_POWER_SENSE_IO) #define self_power PORTAbits.RA2 #else #define self_power 1 #endif // External Transceiver Interface #define tris_usb_vpo TRISBbits.TRISB3 #define tris_usb_vmo TRISBbits.TRISB2 #define tris_usb_rcv TRISAbits.TRISA4 #define tris_usb_vp TRISCbits.TRISC5 #define tris_usb_vm TRISCbits.TRISC4 #define tris_usb_oe TRISCbits.TRISC1 #define tris_usb_suspnd
TRISAbits.TRISA3
// Input
// Output // Output // Input // Input // Input // Output // Output
/** LED ************************************************************/ #define mInitAllLEDs() LATD &= 0xF0; TRISD &= 0xF0; #define mLED_1 #define mLED_2 #define mLED_3 #define mLED_4
LATDbits.LATD0 LATDbits.LATD1 LATDbits.LATD2 LATDbits.LATD3
Komunitas eLearning IlmuKomputer.Com Copyright © 2003-2007 IlmuKomputer.Com
114
#define mLED_1_On() #define mLED_2_On() #define mLED_3_On() #define mLED_4_On()
mLED_1 = 1; mLED_2 = 1; mLED_3 = 1; mLED_4 = 1;
#define mLED_1_Off() #define mLED_2_Off() #define mLED_3_Off() #define mLED_4_Off()
mLED_1 = 0; mLED_2 = 0; mLED_3 = 0; mLED_4 = 0;
#define mLED_1_Toggle() #define mLED_2_Toggle() #define mLED_3_Toggle() #define mLED_4_Toggle()
mLED_1 = !mLED_1; mLED_2 = !mLED_2; mLED_3 = !mLED_3; mLED_4 = !mLED_4;
/** SWITCH *********************************************************/ #define mInitAllSwitches() TRISBbits.TRISB4=1;TRISBbits.TRISB5=1; #define mInitSwitch2() TRISBbits.TRISB4=1; #define mInitSwitch3() TRISBbits.TRISB5=1; #define sw2 PORTBbits.RB4 #define sw3 PORTBbits.RB5 /** POT ************************************************************/ #define mInitPOT() {TRISAbits.TRISA0=1;ADCON0=0x01;ADCON2=0x3C;ADCON2bits.ADFM = 1;} /** SPI : Chip Select Lines ****************************************/ #define tris_cs_temp_sensor TRISBbits.TRISB2 // Output #define cs_temp_sensor LATBbits.LATB2 #define tris_cs_sdmmc TRISBbits.TRISB3 // Output #define cs_sdmmc LATBbits.LATB3 /** SD/MMC *********************************************************/ #define TRIS_CARD_DETECT TRISBbits.TRISB4 // Input #define CARD_DETECT PORTBbits.RB4 #define TRIS_WRITE_DETECT TRISAbits.TRISA4 #define WRITE_DETECT PORTAbits.RA4 #endif #if defined(PIC18F87J50_PIM) #define U1ADDR UADDR #define U1IE UIE #define U1IR UIR #define U1EIR UEIR #define U1EIE UEIE #define U1CON UCON #define U1EP0 UEP0 #define U1CONbits UCONbits #define U1EP1 UEP1 #define U1CNFG1 UCFG #define U1STAT USTAT #define U1EP0bits UEP0bits #define tris_usb_bus_sense TRISBbits.TRISB5 // Input
// Input
#if defined(USE_USB_BUS_SENSE_IO) #define USB_BUS_SENSE PORTBbits.RB5 #else #define USB_BUS_SENSE 1 #endif #define tris_self_power TRISAbits.TRISA2 #if defined(USE_SELF_POWER_SENSE_IO) #define self_power PORTAbits.RA2
Komunitas eLearning IlmuKomputer.Com Copyright © 2003-2007 IlmuKomputer.Com
// Input
115
#else #define self_power #endif
1
// External Transceiver Interface #define tris_usb_vpo #define tris_usb_vmo #define tris_usb_rcv #define tris_usb_vp #define tris_usb_vm #define tris_usb_oe
TRISBbits.TRISB3 TRISBbits.TRISB2 TRISAbits.TRISA4 TRISCbits.TRISC5 TRISCbits.TRISC4 TRISCbits.TRISC1
#define tris_usb_suspnd
TRISAbits.TRISA3
// Output // Output // Input // Input // Input // Output // Output
/** LED ************************************************************/ #define mInitAllLEDs() LATE &= 0xF9; TRISE &= 0xF9; #define mLED_1 #define mLED_2 #define mLED_3 #define mLED_4
LATEbits.LATE1 LATEbits.LATE2 LATDbits.LATD2 LATDbits.LATD3
#define mLED_1_On() #define mLED_2_On() #define mLED_3_On() #define mLED_4_On()
mLED_1 = 1; mLED_2 = 1; mLED_3 = 1; mLED_4 = 1;
#define mLED_1_Off() #define mLED_2_Off() #define mLED_3_Off() #define mLED_4_Off()
mLED_1 = 0; mLED_2 = 0; mLED_3 = 0; mLED_4 = 0;
#define mLED_1_Toggle() #define mLED_2_Toggle() #define mLED_3_Toggle() #define mLED_4_Toggle()
mLED_1 = !mLED_1; mLED_2 = !mLED_2; mLED_3 = !mLED_3; mLED_4 = !mLED_4;
/** SWITCH *********************************************************/ #define mInitAllSwitches() TRISBbits.TRISB4=1;TRISBbits.TRISB4=1; #define mInitSwitch2() TRISBbits.TRISB4=1; #define mInitSwitch3() TRISBbits.TRISB4=1; #define sw2 PORTBbits.RB4 #define sw3 PORTBbits.RB4 /** POT ************************************************************/ ///** P O T ***********************************************************/ #define mInitPOT() {TRISAbits.TRISA0=1;\ WDTCONbits.ADSHR = 1; \ ANCON0bits.PCFG0 = 1; \ WDTCONbits.ADSHR = 0; \ ADCON0=0x01; \ ADCON1=0xBE;} // POT on HPC Explorer /** I 2 C T E M P S E N S E *************************************/ #define mInitI2CPins() TRISC |= 0x18;// RC3 and RC4 are I2C /** SPI : Chip Select Lines ****************************************/ #define tris_cs_temp_sensor TRISBbits.TRISB2 // Output #define cs_temp_sensor LATBbits.LATB2 #define tris_cs_sdmmc TRISBbits.TRISB3 // Output #define cs_sdmmc LATBbits.LATB3 /** SD/MMC *********************************************************/ #define TRIS_CARD_DETECT TRISBbits.TRISB4 // Input #define CARD_DETECT PORTBbits.RB4
Komunitas eLearning IlmuKomputer.Com Copyright © 2003-2007 IlmuKomputer.Com
116
#define TRIS_WRITE_DETECT TRISAbits.TRISA4 #define WRITE_DETECT PORTAbits.RA4 #endif #if defined(EXPLORER_16) #define tris_usb_bus_sense TRISBbits.TRISB5 #define USB_BUS_SENSE 1 #define tris_self_power TRISAbits.TRISA2 #define self_power 1 // External Transceiver Interface #define tris_usb_vpo TRISBbits.TRISB3 #define tris_usb_vmo TRISBbits.TRISB2 #define tris_usb_rcv TRISAbits.TRISA4 #define tris_usb_vp TRISCbits.TRISC5 #define tris_usb_vm TRISCbits.TRISC4 #define tris_usb_oe TRISCbits.TRISC1 #define tris_usb_suspnd TRISAbits.TRISA3
// Input
// Input // Input // Output // Output // Input // Input // Input // Output // Output
/** LED ******************************************************/ #define mInitAllLEDs() LATA &= 0x00; TRISA &= 0xFF00; #define mLED_1 LATAbits.LATA0 #define mLED_2 LATAbits.LATA1 #define mLED_3 LATAbits.LATA2 #define mLED_4 LATAbits.LATA3 #define mLED_1_On() mLED_1 = 1; #define mLED_2_On() mLED_2 = 1; #define mLED_3_On() mLED_3 = 1; #define mLED_4_On() mLED_4 = 1; #define mLED_1_Off() mLED_1 = 0; #define mLED_2_Off() mLED_2 = 0; #define mLED_3_Off() mLED_3 = 0; #define mLED_4_Off() mLED_4 = 0; #define mLED_1_Toggle() mLED_1 = !mLED_1; #define mLED_2_Toggle() mLED_2 = !mLED_2; #define mLED_3_Toggle() mLED_3 = !mLED_3; #define mLED_4_Toggle() mLED_4 = !mLED_4; /** SWITCH *********************************************************/ #define mInitSwitch2() TRISDbits.TRISD6=1; #define mInitSwitch3() TRISDbits.TRISD7=1; #define mInitAllSwitches() mInitSwitch2();mInitSwitch3(); #define sw2 PORTDbits.RD6 //PORTDbits.RD6 #define sw3 PORTDbits.RD7 //PORTDbits.RD7 #endif #endif //HARDWARE_PROFILE_H
8. hid_application.h (C:\HID_ku\Header) /******************************************************************************* USB generic HID header file (c))Microchip Technology, Inc. *******************************************************************/ #ifndef HID_H #define HID_H #endif //HID_H void HandleControlOutReport(void); BOOL ReportSupported(void);
9. usb.h (C:\HID_ku\Header) /******************************************************************************* FileName: usb.h (c) Microchip Technology, Inc. ********************************************************************/ #ifndef _USB_H_
Komunitas eLearning IlmuKomputer.Com Copyright © 2003-2007 IlmuKomputer.Com
117
#define _USB_H_ #include "header/usb_config.h" // Must be defined by the application #include "header/usb_common.h"// Common USB library definitions #include "header/usb_ch9.h" // USB device framework definitions #include "header/usb_hal.h" // Hardware Abstraction Layer interface #if defined( USB_SUPPORT_DEVICE ) #include "header/usb_device.h" // USB Device abstraction layer interface #endif #if defined( USB_SUPPORT_HOST ) #include "header/usb_host.h" // USB Host abstraction layer interface #endif #if defined ( USB_SUPORT_OTG ) #error "USB OTG is not supported." #endif // Section: Host Firmware Version #define USB_MAJOR_VER 1 // Firmware version, major release number. #define USB_MINOR_VER 0 // Firmware version, minor release number. #define USB_DOT_VER 0 // Firmware version, dot release number. #endif // _USB_H_
10. usb_ch9.h (C:\HID_ku\Header) /******************************************************************************* FileName: usb_ch9.h (c) Microchip Technology, Inc. *******************************************************************************/ #ifndef _USB_CH9_H_ #define _USB_CH9_H_ // Section: USB Descriptors #define USB_DESCRIPTOR_DEVICE 0x01 // bDescriptorType for a Device Descriptor. #define USB_DESCRIPTOR_CONFIGURATION 0x02 // bDescriptorType // Configuration Descriptor. #define USB_DESCRIPTOR_STRING 0x03 // bDescriptorType for a String Desc. #define USB_DESCRIPTOR_INTERFACE 0x04 // bDescriptorType for an Interface Desc. #define USB_DESCRIPTOR_ENDPOINT 0x05 // bDescriptorType for an Endpoint Desc. #define USB_DESCRIPTOR_DEVICE_QUALIFIER 0x06 // bDescriptorType for a //Device Qualifier. #define USB_DESCRIPTOR_OTHER_SPEED 0x07 // bDescriptorType for a Other //Speed Configuration. #define USB_DESCRIPTOR_INTERFACE_POWER 0x08 // bDescriptorType for //Interface Power. #define USB_DESCRIPTOR_OTG 0x09 // bDescriptorType for an OTG Descriptor. // USB Device Descriptor Structure typedef struct __attribute__ ((packed)) _USB_DEVICE_DESCRIPTOR { BYTE bLength; // Length of this descriptor. BYTE bDescriptorType; // DEVICE descriptor type (USB_DESCRIPTOR_DEVICE). WORD bcdUSB; // USB Spec Release Number (BCD). BYTE bDeviceClass; // Class code (assigned by the USB-IF). 0xFF-Vendor //secific. BYTE bDeviceSubClass; // Subclass code (assigned by the USB-IF). BYTE bDeviceProtocol; // Protocol code (assigned by the USB-IF). 0xFF-Vendor //specific. BYTE bMaxPacketSize0; // Maximum packet size for endpoint 0. WORD idVendor; // Vendor ID (assigned by the USB-IF). WORD idProduct; // Product ID (assigned by the manufacturer). WORD bcdDevice; // Device release number (BCD). BYTE iManufacturer; // Index of String Descriptor describing the
Komunitas eLearning IlmuKomputer.Com Copyright © 2003-2007 IlmuKomputer.Com
118
BYTE iProduct; BYTE iSerialNumber; BYTE bNumConfigurations; } USB_DEVICE_DESCRIPTOR;
//manufacturer. // Index of String Descriptor describing the product. // Index of String Descriptor with the device's serial //number. // Number of possible configurations.
//USB Configuration Descriptor Structure typedef struct __attribute__ ((packed)) _USB_CONFIGURATION_DESCRIPTOR { BYTE bLength; // Length of this descriptor. BYTE bDescriptorType; // CONFIGURATION descriptor type (USB_DESCRIPTOR_CONFIGURATION). WORD wTotalLength; // Total length of all descriptors for this configuration. BYTE bNumInterfaces; // Number of interfaces in this configuration. BYTE bConfigurationValue; // Value of this configuration (1 based). BYTE iConfiguration; // Index of String Descriptor describing the //configuration. BYTE bmAttributes; // Configuration characteristics. BYTE bMaxPower; // Maximum power consumed by this configuration. } USB_CONFIGURATION_DESCRIPTOR; // Attributes bits #define USB_CFG_DSC_REQUIRED 0x80 // Required attribute #define USB_CFG_DSC_SELF_PWR (0x40|USB_CFG_DSC_REQUIRED) // Device is self powered. #define USB_CFG_DSC_REM_WAKE (0x20|USB_CFG_DSC_REQUIRED) // Device can request remote wakup // USB Interface Descriptor Structure typedef struct __attribute__ ((packed)) _USB_INTERFACE_DESCRIPTOR { BYTE bLength; // Length of this descriptor. BYTE bDescriptorType; // INTERFACE descriptor type (USB_DESCRIPTOR_INTERFACE). BYTE bInterfaceNumber; // Number of this interface (0 based). BYTE bAlternateSetting; // Value of this alternate interface setting. BYTE bNumEndpoints; // Number of endpoints in this interface. BYTE bInterfaceClass; // Class code (assigned by the USB-IF). 0xFF-Vendor //specific. BYTE bInterfaceSubClass; // Subclass code (assigned by the USB-IF). BYTE bInterfaceProtocol; // Protocol code (assigned by the USB-IF). BYTE iInterface; // Index of String Descriptor describing the interface. } USB_INTERFACE_DESCRIPTOR; // USB Endpoint Descriptor Structure typedef struct __attribute__ ((packed)) _USB_ENDPOINT_DESCRIPTOR { BYTE bLength; // Length of this descriptor. BYTE bDescriptorType; // ENDPOINT descriptor type (USB_DESCRIPTOR_ENDPOINT). BYTE bEndpointAddress; // Endpoint address. Bit 7 indicates direction (0=OUT, 1=IN). BYTE bmAttributes; // Endpoint transfer type. WORD wMaxPacketSize; // Maximum packet size. BYTE bInterval; // Polling interval in frames. } USB_ENDPOINT_DESCRIPTOR; // Endpoint Direction #define EP_DIR_IN #define EP_DIR_OUT
0x80 // Data flows from device to host 0x00 // Data flows from host to device
// USB Endpoint Attributes #define EP_ATTR_CONTROL (0<<0) #define EP_ATTR_ISOCH (1<<0) #define EP_ATTR_BULK (2<<0) #define EP_ATTR_INTR (3<<0)
Komunitas eLearning IlmuKomputer.Com Copyright © 2003-2007 IlmuKomputer.Com
// Endoint used for control transfers // Endpoint used for isochronous transfers // Endpoint used for bulk transfers // Endpoint used for interrupt transfers
119
// Section: Synchronization Types (for isochronous enpoints) #define EP_ATTR_NO_SYNC (0<<2) // No Synchronization #define EP_ATTR_ASYNC (1<<2) // Asynchronous #define EP_ATTR_ADAPT (2<<2) // Adaptive synchronization #define EP_ATTR_SYNC (3<<2) // Synchronous // Section: Usage Types (for isochronous endpoints) #define EP_ATTR_DATA (0<<4) // Data Endpoint #define EP_ATTR_FEEDBACK (1<<4) // Feedback endpoint #define EP_ATTR_IMP_FB (2<<4) // Implicit Feedback data EP // Section: Max Packet Sizes #define EP_MAX_PKT_INTR_LS 8 #define EP_MAX_PKT_INTR_FS 64 #define EP_MAX_PKT_ISOCH_FS 1023 #define EP_MAX_PKT_BULK_FS 64 #define EP_LG_PKT_BULK_FS 32 #define EP_MED_PKT_BULK_FS 16 #define EP_SM_PKT_BULK_FS 8
// Max low-speed interrupt packet // Max full-speed interrupt packet // Max full-speed isochronous packet // Max full-speed bulk packet // Large full-speed bulk packet // Medium full-speed bulk packet // Small full-speed bulk packet
// USB OTG Descriptor Structure typedef struct __attribute__ ((packed)) _USB_OTG_DESCRIPTOR { BYTE bLength; // Length of this descriptor. BYTE bDescriptorType; // OTG descriptor type (USB_DESCRIPTOR_OTG). BYTE bmAttributes; // OTG attributes. } USB_OTG_DESCRIPTOR; // Section: USB String Descriptor Structure typedef struct __attribute__ ((packed)) _USB_STRING_DSC { BYTE bLength; // Size of this descriptor BYTE bDescriptorType; // Type, USB_DSC_STRING } USB_STRING_DESCRIPTOR; // Section: USB Device Qualifier Descriptor Structure typedef struct __attribute__ ((packed)) _USB_DEVICE_QUALIFIER_DESCRIPTOR { BYTE bLength; // Size of this descriptor BYTE bType; // Type, always USB_DESCRIPTOR_DEVICE_QUALIFIER WORD bcdUSB; // USB spec version, in BCD BYTE bDeviceClass; // Device class code BYTE bDeviceSubClass; // Device sub-class code BYTE bDeviceProtocol; // Device protocol BYTE bMaxPacketSize0; // EP0, max packet size BYTE bNumConfigurations; // Number of "other-speed" configurations BYTE bReserved; // Always zero (0) } USB_DEVICE_QUALIFIER_DESCRIPTOR; // Section: USB Setup Packet Structure typedef struct __attribute__ ((packed)) SetupPkt { union // offset description { BYTE bmRequestType; // 0 Bit-map of request type struct { BYTE recipient: 5; // Recipient of the request BYTE type: 2; // Type of request BYTE direction: 1; // Direction of data X-fer };
Komunitas eLearning IlmuKomputer.Com Copyright © 2003-2007 IlmuKomputer.Com
120
}requestInfo; BYTE UINT16 UINT16 UINT16
bRequest; wValue; wIndex; wLength;
// // // //
1 2 4 6
Request type Depends on bRequest Depends on bRequest Depends on bRequest
} SETUP_PKT, *PSETUP_PKT; // Section: USB Specification Constants #define PID_OUT 0x1 // PID for an OUT token #define PID_ACK 0x2 // PID for an ACK handshake #define PID_DATA0 0x3 // PID for DATA0 data #define PID_PING 0x4 // Special PID PING #define PID_SOF 0x5 // PID for a SOF token #define PID_NYET 0x6 // PID for a NYET handshake #define PID_DATA2 0x7 // PID for DATA2 data #define PID_SPLIT 0x8 // Special PID SPLIT #define PID_IN 0x9 // PID for a IN token #define PID_NAK 0xA // PID for a NAK handshake #define PID_DATA1 0xB // PID for DATA1 data #define PID_PRE 0xC // Special PID PRE (Same as PID_ERR) #define PID_ERR 0xC // Special PID ERR (Same as PID_PRE) #define PID_SETUP 0xD // PID for a SETUP token #define PID_STALL 0xE // PID for a STALL handshake #define PID_MDATA 0xF // PID for MDATA data #define PID_MASK_DATA 0x03 // Data PID mask #define PID_MASK_DATA_SHIFTED (PID_MASK_DATA << 2) // Data PID shift to proper position #define USB_TOKEN_OUT 0x01 // U1TOK - OUT token #define USB_TOKEN_IN 0x09 // U1TOK - IN token #define USB_TOKEN_SETUP 0x0D // U1TOK - SETUP token #define OTG_HNP_SUPPORT 0x02 // OTG Descriptor bmAttributes - HNP support flag #define OTG_SRP_SUPPORT 0x01 // OTG Descriptor bmAttributes - SRP support flag #define USB_IN_EP 0x80 // IN endpoint mask #define USB_OUT_EP 0x00 // OUT endpoint mask #define USB_REQUEST_GET_STATUS 0 // Standard Device Request - GET STATUS #define USB_REQUEST_CLEAR_FEATURE 1 // Standard Device Request - CLEAR FEATURE #define USB_REQUEST_SET_FEATURE 3 // Standard Device Request - SET FEATURE #define USB_REQUEST_SET_ADDRESS 5 // Standard Device Request - SET ADDRESS #define USB_REQUEST_GET_DESCRIPTOR 6 // Standard Device Request - GET DESCRIPTOR #define USB_REQUEST_SET_DESCRIPTOR 7 // Standard Device Request - SET DESCRIPTOR #define USB_REQUEST_GET_CONFIGURATION 8 // Standard Device Request - GET CONFIGURATION #define USB_REQUEST_SET_CONFIGURATION 9 // Standard Device Request - SET CONFIGURATION #define USB_REQUEST_GET_INTERFACE 10 // Standard Device Request - GET INTERFACE #define USB_REQUEST_SET_INTERFACE 11 // Standard Device Request - SET INTERFACE #define USB_REQUEST_SYNCH_FRAME 12 // Standard Device Request - SYNCH FRAME #define USB_FEATURE_ENDPOINT_HALT 0 // CLEAR/SET FEATURE - Endpoint Halt #define USB_FEATURE_DEVICE_REMOTE_WAKEUP 1
Komunitas eLearning IlmuKomputer.Com Copyright © 2003-2007 IlmuKomputer.Com
121
// CLEAR/SET FEATURE - Device remote wake-up #define USB_FEATURE_TEST_MODE 2 // CLEAR/SET FEATURE - Test mode // Section: Setup Data Constants #define USB_SETUP_HOST_TO_DEVICE 0x00 // Device Request bmRequestType transfer direction - host to device transfer #define USB_SETUP_DEVICE_TO_HOST 0x80 // Device Request bmRequestType transfer direction - device to host transfer #define USB_SETUP_TYPE_STANDARD 0x00 // Device Request bmRequestType type - standard #define USB_SETUP_TYPE_CLASS 0x20 // Device Request bmRequestType type - class #define USB_SETUP_TYPE_VENDOR 0x40 // Device Request bmRequestType type - vendor #define USB_SETUP_RECIPIENT_DEVICE 0x00 // Device Request bmRequestType recipient - device #define USB_SETUP_RECIPIENT_INTERFACE 0x01 // Device Request bmRequestType recipient - interface #define USB_SETUP_RECIPIENT_ENDPOINT 0x02 // Device Request bmRequestType recipient - endpoint #define USB_SETUP_RECIPIENT_OTHER 0x03 // Device Request bmRequestType recipient - other // Section: OTG SET FEATURE Constants #define OTG_FEATURE_B_HNP_ENABLE 3 // SET FEATURE OTG - Enable B device to perform HNP #define OTG_FEATURE_A_HNP_SUPPORT 4 // SET FEATURE OTG - A device supports HNP #define OTG_FEATURE_A_ALT_HNP_SUPPORT 5 // SET FEATURE OTG - Another port on the A device supports HNP // Section: USB Endpoint Transfer Types #define USB_TRANSFER_TYPE_CONTROL // Endpoint is a control endpoint. #define USB_TRANSFER_TYPE_ISOCHRONOUS // Endpoint is an isochronous endpoint. #define USB_TRANSFER_TYPE_BULK // Endpoint is a bulk endpoint. #define USB_TRANSFER_TYPE_INTERRUPT // Endpoint is an interrupt endpoint.
0x00 0x01 0x02 0x03
// Section: Standard Feature Selectors for CLEAR_FEATURE Requests #define USB_FEATURE_ENDPOINT_STALL 0 // Endpoint recipient #define USB_FEATURE_DEVICE_REMOTE_WAKEUP 1 // Device recipient #define USB_FEATURE_TEST_MODE 2 // Device recipient // Section: USB Class Code Definitions #define USB_HUB_CLASSCODE #endif // _USB_CH9_H_
0x09
// Class code for a hub.
11. usb_common.h (C:\HID_ku\Header) /******************************************************************* FileName: usb_common.h (c)) Microchip Technology, Inc. *****************************************************************/ #ifndef _USB_COMMON_H_ #define _USB_COMMON_H_ #include #include "header/GenericTypeDefs.h" // Section: USB Constants #define USB_SUCCESS 0x00 // USB operation successful.
Komunitas eLearning IlmuKomputer.Com Copyright © 2003-2007 IlmuKomputer.Com
122
#define USB_INVALID_STATE 0x01 // Operation cannot be performed in current state. #define USB_BUSY 0x02 // A transaction is already in progress. #define USB_ILLEGAL_REQUEST 0x03 // Cannot perform requested operation. #define USB_INVALID_CONFIGURATION 0x04 // Configuration descriptor not found. #define USB_MEMORY_ALLOCATION_ERROR 0x05 // Out of dynamic memory. #define USB_UNKNOWN_DEVICE 0x06 // Device with specified address is not attached. #define USB_CANNOT_ENUMERATE 0x07 // Cannot enumerate the attached device. #define USB_EVENT_QUEUE_FULL 0x08 // Event queue was full when an event occured. #define USB_ENDPOINT_BUSY 0x10 // Endpoint is currently processing a transaction. #define USB_ENDPOINT_STALLED 0x11 // Endpoint is currently stalled. User must clear the condition. #define USB_ENDPOINT_ERROR 0x12 // Will need more than this eventually #define USB_ENDPOINT_ERROR_ILLEGAL_PID 0x13 // Illegal PID received. #define USB_ENDPOINT_NOT_FOUND 0x14 // Requested endpoint does not exist on device. #define USB_ENDPOINT_ILLEGAL_DIRECTION 0x15 // Reads must be performe on IN endpoints, writes on OUT endpoints. //#define USB_ENDPOINT_TRANSACTION_IN_PROGRESS 0x16 #define USB_ENDPOINT_NAK_TIMEOUT 0x17 // Too many NAK's occurred while waiting for the current transaction. #define USB_ENDPOINT_ILLEGAL_TYPE 0x18 // Transfer type must match endpoint description. #define USB_ENDPOINT_UNRESOLVED_STATE 0x19 // Endpoint is in an unknown state after completing a transaction. #define USB_ENDPOINT_ERROR_BIT_STUFF 0x20 // USB Module - Bit stuff error. #define USB_ENDPOINT_ERROR_DMA 0x21 // USB Module - DMA error. #define USB_ENDPOINT_ERROR_TIMEOUT 0x22 // USB Module - Bus timeout. #define USB_ENDPOINT_ERROR_DATA_FIELD 0x23 // USB Module - Data field size error. #define USB_ENDPOINT_ERROR_CRC16 0x24 // USB Module - CRC16 failure. #define USB_ENDPOINT_ERROR_END_OF_FRAME 0x25 // USB Module - End of Frame error. #define USB_ENDPOINT_ERROR_PID_CHECK 0x26 // USB Module - Illegal PID received. #define USB_ENDPOINT_ERROR_BMX 0x27 // USB Module - Bus Matrix error. #define USB_ERROR_INSUFFICIENT_POWER 0x28 // Too much power was requested // Section: Return values for USBHostDeviceStatus() #define USB_DEVICE_STATUS 0x30 // Offset for USBHostDeviceStatus() return codes #define USB_DEVICE_ATTACHED (USB_DEVICE_STATUS | 0x30) // Device is attached and running #define USB_DEVICE_DETACHED (USB_DEVICE_STATUS | 0x01) // No device is attached #define USB_DEVICE_ENUMERATING (USB_DEVICE_STATUS | 0x02) // Device is enumerating #define USB_HOLDING_OUT_OF_MEMORY (USB_DEVICE_STATUS | 0x03) // Not enough heap space available
Komunitas eLearning IlmuKomputer.Com Copyright © 2003-2007 IlmuKomputer.Com
123
#define USB_HOLDING_UNSUPPORTED_DEVICE (USB_DEVICE_STATUS | 0x04) // Invalid configuration or unsupported class #define USB_HOLDING_UNSUPPORTED_HUB (USB_DEVICE_STATUS | 0x05) // Hubs are not supported #define USB_HOLDING_INVALID_CONFIGURATION (USB_DEVICE_STATUS | 0x06) Invalid configuration requested #define USB_HOLDING_PROCESSING_CAPACITY (USB_DEVICE_STATUS | 0x07) // Processing requirement excessive #define USB_HOLDING_POWER_REQUIREMENT (USB_DEVICE_STATUS | 0x08) // Power requirement excessive #define USB_HOLDING_CLIENT_INIT_ERROR (USB_DEVICE_STATUS | 0x09) // Client driver failed to initialize #define USB_DEVICE_SUSPENDED (USB_DEVICE_STATUS | 0x0A) // Device is suspended #define USB_ERROR_CLASS_DEFINED 0x50 // Offset for application defined errors #define USB_SINGLE_DEVICE_ADDRESS 0x01 // Default USB device address (single device support)
//
// SECTION: USB DATA TYPES typedef union { BYTE bitmap; struct { BYTE ep_num: 4; BYTE zero_pkt: 1; BYTE dts: 1; BYTE force_dts: 1; BYTE direction: 1; }field; } TRANSFER_FLAGS; #define USB_EP0 #define USB_EP1 #define USB_EP2 #define USB_EP3 #define USB_EP4 #define USB_EP5 #define USB_EP6 #define USB_EP7 #define USB_EP8 #define USB_EP9 #define USB_EP10 #define USB_EP11 #define USB_EP12 #define USB_EP13 #define USB_EP14 #define USB_EP15
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
#define USB_TRANSMIT 0x80 // Data will be transmitted to the USB #define USB_RECEIVE 0x00 // Data will be received from the USB #define USB_FORCE_DTS 0x40 // Forces data toggle sync as below: #define USB_DTS_MASK 0x20 // Mask for DTS bit (below) #define USB_ZERO_PKT 0x10 // End transfer w/a short or zero-length packet #define USB_DATA0 0x00|USB_FORCE_DTS // Force DATA0 #define USB_DATA1 0x20|USB_FORCE_DTS // Force DATA1 #define USB_SETUP_PKT USB_RECEIVE|USB_DATA0|USB_EP0 // Setup Packet #define USB_SETUP_DATA USB_DATA1|USB_ZERO_PKT|USB_EP0 // Setup-transfer Data Packet #define USB_SETUP_STATUS USB_DATA1|USB_EP0
Komunitas eLearning IlmuKomputer.Com Copyright © 2003-2007 IlmuKomputer.Com
124
// Setup-transfer Status Packet #define USB_EP_NUM_MASK 0x0F // Endpoint number (ep_num) mask #define XFLAGS(f) ((TRANSFER_FLAGS)((BYTE)(f))) // Initialization Macro typedef enum { // No event occured (NULL event) EVENT_NONE = 0, EVENT_TRANSFER, EVENT_SOF, EVENT_RESUME, EVENT_SUSPEND, EVENT_RESET, EVENT_ATTACH, EVENT_DETACH, EVENT_HUB_ATTACH, EVENT_STALL, EVENT_SETUP, EVENT_VBUS_SES_REQUEST, EVENT_VBUS_OVERCURRENT, EVENT_VBUS_REQUEST_POWER, EVENT_VBUS_RELEASE_POWER, EVENT_VBUS_POWER_AVAILABLE, EVENT_UNSUPPORTED_DEVICE, EVENT_CANNOT_ENUMERATE, EVENT_CLIENT_INIT_ERROR, EVENT_OUT_OF_MEMORY, EVENT_UNSPECIFIED_ERROR, EVENT_GENERIC_BASE = 100, // Offset for Generic class events EVENT_MSD_BASE = 200, // Offset for Mass Storage Device class events EVENT_HID_BASE = 300, // Offset for Human Interface Device class events EVENT_USER_BASE = 10000, // Add integral values to this event number EVENT_BUS_ERROR = UINT_MAX } USB_EVENT; typedef struct _transfer_event_data { TRANSFER_FLAGS flags; UINT32 size; BYTE pid;
// Transfer flags (see above) // Actual number of bytes transferred // Packet ID
} USB_TRANSFER_EVENT_DATA; typedef struct _vbus_power_data { BYTE port; // Physical port number BYTE current; // Current in 2mA units } USB_VBUS_POWER_EVENT_DATA; typedef BOOL (*USB_EVENT_HANDLER) ( USB_EVENT event, void *data, unsigned int size ); #ifndef USBInitialize #if defined( USB_SUPPORT_DEVICE ) #if defined( USB_SUPPORT_HOST ) #if defined( USB_SUPORT_OTG ) #error "USB OTG is not yet supported." #else #define USBInitialize(f) \ (USBDEVInitialize(f) && USBHostInit(f)) ? \ TRUE : FALSE #endif #else #define USBInitialize(f) USBDEVInitialize(f)
Komunitas eLearning IlmuKomputer.Com Copyright © 2003-2007 IlmuKomputer.Com
125
#endif #else #if defined( USB_SUPPORT_HOST ) #define USBInitialize(f) USBHostInit(f) #else #error "Application must define support mode in usb_config.h" #endif #endif #endif #ifndef USBTasks // Implemented as a macro that can be overridden. #if defined( USB_SUPPORT_DEVICE ) #if defined( USB_SUPPORT_HOST ) #if defined( USB_SUPORT_OTG ) #error "USB OTG is not yet supported." #else #define USBTasks() {USBHostTasks(); USBHALHandleBusEvent();} #endif #else #define USBTasks() USBHALHandleBusEvent() #endif #else #if defined( USB_SUPPORT_HOST ) #define USBTasks() USBHostTasks() #else #error "Application must define support mode in usb_config.h" #endif #endif #endif #endif // _USB_COMMON_H_
12. usb_config.h (C:\HID_ku\Header) /******************************************************************** FileName: USBConfig.h (c))Microchip Technology, Inc. *****************************************************************/ #ifndef USBCFG_H #define USBCFG_H #include "header/usb_function_hid.h" #include "header/hid_application.h" #define EP0_BUFF_SIZE 8 // 8, 16, 32, or 64 #define MAX_NUM_INT 1 // For tracking Alternate Setting #define HID_EP 1 //the maximum transfer size of EP1 #define USB_MAX_DATA_SIZE_EP1 64 #define USB_NUM_MESSAGES_EP1 1 #define USB_PING_PONG__NO_PING_PONG #define USB_PING_PONG__EP0_OUT_ONLY #define USB_PING_PONG__FULL_PING_PONG #define USB_PING_PONG__ALL_BUT_EP0
0x00 0x01 0x02 0x03
#define USB_PING_PONG_MODE USB_PING_PONG__NO_PING_PONG #define USB_EP0_BUFF_SIZE 8 #define USB_POLLING #define USB_MAX_EP_NUMBER
Komunitas eLearning IlmuKomputer.Com Copyright © 2003-2007 IlmuKomputer.Com
1
126
/* Parameter definitions are defined in usbd.h */ #define MODE_PP USB_PING_PONG_MODE #define UCFG_VAL _PUEN|_TRINT|_FS|MODE_PP #define USE_USB_BOOTLOADER #define SUPPORT_SET_DSC #define SUPPORT_SYNC_FRAME #define USB_USE_HID #define USB_SUPPORT_DEVICE #define HID_INTF_ID #define HID_UEP #define HID_BD_OUT #define HID_INT_OUT_EP_SIZE #define HID_BD_IN #define HID_INT_IN_EP_SIZE #define HID_NUM_OF_DSC #define HID_RPT01_SIZE
0x00 UEP1 USB_EP_1_OUT 64 USB_EP_1_IN 64 1 47
#define HID_INPUT_REPORT_BYTES 8 #define HID_OUTPUT_REPORT_BYTES 1 #define HID_FEATURE_REPORT_BYTES 2 #define USBGEN_EP_SIZE 64 /** DEFINITIONS ****************************************************/ #endif //USBCFG_H
13. usb_device.h (C:\HID_ku\Header) /******************************************************************/ FileName: usb_device.h (c) )Microchip Technology, Inc. *******************************************************************/ #ifndef USBDEVICE_H #define USBDEVICE_H //DOM-IGNORE-END #include "header\usb_ch9.h" #include "header\usb_hal.h" #define _EP_IN #define _EP_OUT #define _EP01_OUT #define _EP01_IN #define _EP02_OUT #define _EP02_IN #define _EP03_OUT #define _EP03_IN #define _EP04_OUT #define _EP04_IN #define _EP05_OUT #define _EP05_IN #define _EP06_OUT #define _EP06_IN #define _EP07_OUT #define _EP07_IN #define _EP08_OUT #define _EP08_IN #define _EP09_OUT #define _EP09_IN #define _EP10_OUT #define _EP10_IN #define _EP11_OUT
0x80 0x00 0x01 0x81 0x02 0x82 0x03 0x83 0x04 0x84 0x05 0x85 0x06 0x86 0x07 0x87 0x08 0x88 0x09 0x89 0x0A 0x8A 0x0B
Komunitas eLearning IlmuKomputer.Com Copyright © 2003-2007 IlmuKomputer.Com
127
#define _EP11_IN 0x8B #define _EP12_OUT 0x0C #define _EP12_IN 0x8C #define _EP13_OUT 0x0D #define _EP13_IN 0x8D #define _EP14_OUT 0x0E #define _EP14_IN 0x8E #define _EP15_OUT 0x0F #define _EP15_IN 0x8F /* Configuration Attributes */ #define _DEFAULT (0x01<<7) #define _SELF (0x01<<6) #define _RWU (0x01<<5) /* Endpoint Transfer Type */ #define _CTRL #define _ISO #define _BULK #define _INT
//Default Value (Bit 7 is set) //Self-powered (Supports if set) //Remote Wakeup (Supports if set)
0x00 0x01 0x02 0x03
//Control Transfer //Isochronous Transfer //Bulk Transfer //Interrupt Transfer
/* Isochronous Endpoint Synchronization Type */ #define _NS (0x00<<2) //No Synchronization #define _AS (0x01<<2) //Asynchronous #define _AD (0x02<<2) //Adaptive #define _SY (0x03<<2) //Synchronous /* Isochronous Endpoint Usage Type */ #define _DE (0x00<<4) #define _FE (0x01<<4) #define _IE (0x02<<4) #define _ROM #define _RAM
//Data endpoint //Feedback endpoint //Implicit feedback Data endpoint
USB_INPIPES_ROM USB_INPIPES_RAM
typedef union _CTRL_TRF_SETUP { /** Standard Device Requests ***********************************/ struct { BYTE bmRequestType; //from table 9-2 of USB2.0 spec BYTE bRequest; WORD wValue; WORD wIndex; WORD wLength; }; struct { unsigned :8; unsigned :8; WORD_VAL W_Value; //from table 9-2 of USB2.0 spec, allows byte/bitwise access WORD_VAL W_Index; WORD_VAL W_Length; }; struct { unsigned Recipient:5; //Device,Interface,Endpoint,Other unsigned RequestType:2; //Standard,Class,Vendor,Reserved unsigned DataDir:1; //Host-to-device,Device-to-host unsigned :8; BYTE bFeature; unsigned :8; unsigned :8;
//DEVICE_REMOTE_WAKEUP,ENDPOINT_HALT
Komunitas eLearning IlmuKomputer.Com Copyright © 2003-2007 IlmuKomputer.Com
128
unsigned :8; unsigned :8; unsigned :8; }; struct { unsigned :8; unsigned :8; BYTE bDscIndex; //For Configuration and String DSC Only BYTE bDescriptorType; //Device,Configuration,String WORD wLangID; //Language ID unsigned :8; unsigned :8; }; struct { unsigned :8; unsigned :8; BYTE_VAL bDevADR; //Device Address 0-127 BYTE bDevADRH; //Must equal zero unsigned :8; unsigned :8; unsigned :8; unsigned :8; }; struct { unsigned :8; unsigned :8; BYTE bConfigurationValue; //Configuration Value 0-255 BYTE bCfgRSD; //Must equal zero (Reserved) unsigned :8; unsigned :8; unsigned :8; unsigned :8; }; struct { unsigned :8; unsigned :8; BYTE bAltID; //Alternate Setting Value 0-255 BYTE bAltID_H; //Must equal zero BYTE bIntfID; //Interface Number Value 0-255 BYTE bIntfID_H; //Must equal zero unsigned :8; unsigned :8; }; struct { unsigned :8; unsigned :8; unsigned :8; unsigned :8; BYTE bEPID; //Endpoint ID (Number & Direction) BYTE bEPID_H; //Must equal zero unsigned :8; unsigned :8; }; struct { unsigned :8; unsigned :8; unsigned :8; unsigned :8;
Komunitas eLearning IlmuKomputer.Com Copyright © 2003-2007 IlmuKomputer.Com
129
unsigned EPNum:4; unsigned :3; unsigned EPDir:1; unsigned :8; unsigned :8; unsigned :8;
//Endpoint Number 0-15 //Endpoint Direction: 0-OUT, 1-IN
}; /** End: Standard Device Requests ******************************/ } CTRL_TRF_SETUP; typedef struct { union { BYTE *bRam; ROM BYTE *bRom; WORD *wRam; ROM WORD *wRom; }pSrc; union { struct { //is it a control transfer? BYTE ctrl_trf_mem :1; BYTE reserved :5; //include a zero length packet after //data is done if data_size%ep_size = 0? BYTE includeZero :1; //is this PIPE currently in use BYTE busy :1; }bits; BYTE Val; }info; WORD_VAL wCount; }PIPE; //Various options for setting the PIPES #define USB_INPIPES_ROM #define USB_INPIPES_RAM #define USB_INPIPES_BUSY #define USB_INPIPES_INCLUDE_ZERO #define USB_INPIPES_NO_DATA #define USB_INPIPES_NO_OPTIONS #define USB_EP0_ROM #define USB_EP0_RAM #define USB_EP0_BUSY #define USB_EP0_INCLUDE_ZERO #define USB_EP0_NO_DATA #define USB_EP0_NO_OPTIONS
0x00 //Data comes from RAM 0x01 //Data comes from ROM 0x80 //The PIPE is busy 0x40 //include a trailing zero packet 0x00 //no data to send 0x00 //no options set USB_INPIPES_ROM USB_INPIPES_RAM USB_INPIPES_BUSY USB_INPIPES_INCLUDE_ZERO USB_INPIPES_NO_DATA USB_INPIPES_NO_OPTIONS
/******************************************************************** * Standard Request Codes * USB 2.0 Spec Ref Table 9-4 *******************************************************************/ #define GET_STATUS 0 #define CLR_FEATURE 1 #define SET_FEATURE 3 #define SET_ADR 5 #define GET_DSC 6 #define SET_DSC 7
Komunitas eLearning IlmuKomputer.Com Copyright © 2003-2007 IlmuKomputer.Com
130
#define GET_CFG #define SET_CFG #define GET_INTF #define SET_INTF #define SYNCH_FRAME
8 9 10 11 12
/* Standard Feature Selectors */ #define DEVICE_REMOTE_WAKEUP #define ENDPOINT_HALT
0x01 0x00
/* USB Device States - To be used with [BYTE usb_device_state] */ #define DETACHED_STATE 0x00 #define ATTACHED_STATE 0x01 #define POWERED_STATE 0x02 #define DEFAULT_STATE 0x04 #define ADR_PENDING_STATE 0x08 #define ADDRESS_STATE 0x10 #define CONFIGURED_STATE 0x20 /* UCFG Initialization Parameters */ #if defined(__18CXX) #define _LS 0x00 // Use Low-Speed USB Mode #define _FS 0x04 // Use Full-Speed USB Mode #define _TRINT 0x00 // Use internal transceiver #define _TREXT 0x08 // Use external transceiver #define _PUEN 0x10 // Use internal pull-up resistor #define _OEMON 0x40 // Use SIE output indicator #elif defined(__C30__) #define _LS 0x00 // Use Low-Speed USB Mode #define _FS 0x00 // Use Full-Speed USB Mode #define _TRINT 0x00 // Use internal transceiver #define _TREXT 0x00 // Use external transceiver #define _PUEN 0x00 // Use internal pull-up resistor #define _OEMON 0x00 // Use SIE output indicator #endif //#define _UTEYE 0x80 // Use Eye-Pattern test /* UEPn Initialization Parameters */ #if defined (__18CXX) #define EP_CTRL 0x06 #define EP_OUT 0x0C #define EP_IN 0x0A #define EP_OUT_IN 0x0E
// Cfg Control pipe for this ep // Cfg OUT only pipe for this ep // Cfg IN only pipe for this ep // Cfg both OUT & IN pipes for this ep
// Handshake should be disable for isoch #define USB_HANDSHAKE_ENABLED 0x10 #define USB_HANDSHAKE_DISABLED 0x00 #define USB_OUT_ENABLED 0x04 #define USB_OUT_DISABLED 0x00 #define USB_IN_ENABLED 0x02 #define USB_IN_DISABLED 0x00 #define USB_ALLOW_SETUP 0x00 #define USB_DISALLOW_SETUP 0x08 #define USB_STALL_ENDPOINT 0x01 #elif defined(__C30__) #define EP_CTRL 0x0C // Cfg Control pipe for this ep #define EP_OUT 0x18 // Cfg OUT only pipe for this ep #define EP_IN 0x14 // Cfg IN only pipe for this ep #define EP_OUT_IN 0x1C // Cfg both OUT & IN pipes for this ep #define HSHK_EN 0x01 // Enable handshake packet // Handshake should be disable for isoch #define USB_HANDSHAKE_ENABLED 0x01 #define USB_HANDSHAKE_DISABLED 0x00
Komunitas eLearning IlmuKomputer.Com Copyright © 2003-2007 IlmuKomputer.Com
131
#define USB_OUT_ENABLED #define USB_OUT_DISABLED #define USB_IN_ENABLED #define USB_IN_DISABLED #define USB_ALLOW_SETUP #define USB_DISALLOW_SETUP
0x08 0x00 0x04 0x00 0x00 0x10
#define USB_STALL_ENDPOINT #endif
0x02
#define USB_HANDLE volatile BDT_ENTRY* #if !defined(USBDEVICE_C) /** EXTERNS ********************************************************/ //Definitions for the BDT #if (USB_PING_PONG_MODE == USB_PING_PONG__NO_PING_PONG) extern volatile BDT_ENTRY BDT[(USB_MAX_EP_NUMBER + 1) * 2]; #elif (USB_PING_PONG_MODE == USB_PING_PONG__EP0_OUT_ONLY) extern volatile BDT_ENTRY BDT[((USB_MAX_EP_NUMBER+1) * 2)+1]; #elif (USB_PING_PONG_MODE == USB_PING_PONG__FULL_PING_PONG) extern volatile BDT_ENTRY BDT[(USB_MAX_EP_NUMBER + 1) * 4]; #elif (USB_PING_PONG_MODE == USB_PING_PONG__ALL_BUT_EP0) extern volatile BDT_ENTRY BDT[((USB_MAX_EP_NUMBER + 1) * 4)-2]; #else #error "No ping pong mode defined." #endif //Device descriptor extern ROM USB_DEVICE_DESCRIPTOR device_dsc; //Configuration descriptor extern ROM BYTE configDescriptor1[]; //Array of configuration descriptors extern ROM BYTE *ROM USB_CD_Ptr[]; //Array of string descriptors extern ROM BYTE *ROM USB_SD_Ptr[]; #if defined(USB_USE_HID) //Class specific - HID report descriptor #if !defined(__USB_DESCRIPTORS_C) extern ROM struct{BYTE report[HID_RPT01_SIZE];} hid_rpt01; #endif #endif //Buffer for control transfers extern volatile CTRL_TRF_SETUP SetupPkt; // 8-byte only //Buffer for control transfer data extern volatile BYTE CtrlTrfData[EP0_BUFF_SIZE]; #if defined(USB_USE_HID) //class specific data buffers extern volatile unsigned char hid_report_out[HID_INT_OUT_EP_SIZE]; extern volatile unsigned char hid_report_in[HID_INT_IN_EP_SIZE]; extern volatile unsigned char hid_report_feature[EP0_BUFF_SIZE]; #endif #endif /* Control Transfer States */ #define WAIT_SETUP 0 #define CTRL_TRF_TX 1 #define CTRL_TRF_RX 2 /* v2.1 fix - Short Packet States - Used by Control Transfer Read - CTRL_TRF_TX */ #define SHORT_PKT_NOT_USED 0 #define SHORT_PKT_PENDING 1 #define SHORT_PKT_SENT 2 /* USB PID: Token Types - See chapter 8 in the USB specification */ #define SETUP_TOKEN 0x0D // 0b00001101 #define OUT_TOKEN 0x01 // 0b00000001 #define IN_TOKEN 0x09 // 0b00001001 /* bmRequestType Definitions */
Komunitas eLearning IlmuKomputer.Com Copyright © 2003-2007 IlmuKomputer.Com
132
#define HOST_TO_DEV #define DEV_TO_HOST #define STANDARD #define CLASS #define VENDOR #define RCPT_DEV #define RCPT_INTF #define RCPT_EP #define RCPT_OTH
0 1 0x00 0x01 0x02 0 1 2 3
/** EXTERNS ********************************************************/ #if !defined(USBDEVICE_C) extern BYTE USBDeviceState; extern BYTE USBActiveConfiguration; extern USB_VOLATILE PIPE inPipes[1]; extern volatile BDT_ENTRY *pBDTEntryIn[USB_MAX_EP_NUMBER+1]; #endif /** PUBLIC PROTOTYPES **********************************************/ void USBDeviceTasks(void); void USBRemoteWakeup(void); void USBSoftDetach(void); void USBCtrlEPService(void); void USBCtrlTrfSetupHandler(void); void USBCtrlTrfInHandler(void); void USBCheckStdRequest(void); void USBStdGetDscHandler(void); void USBCtrlEPServiceComplete(void); void USBCtrlTrfTxService(void); void USBPrepareForNextSetupTrf(void); void USBCtrlTrfRxService(void); void USBStdSetCfgHandler(void); void USBStdGetStatusHandler(void); void USBStdFeatureReqHandler(void); void USBCtrlTrfOutHandler(void); BOOL USBIsTxBusy(BYTE EPNumber); void USBPut(BYTE EPNum, BYTE Data); void USBEPService(void); void USBConfigureEndpoint(BYTE EPNum, BYTE direction); void USBProtocolResetHandler(void); void USBWakeFromSuspend(void); void USBSuspend(void); void USBStallHandler(void); volatile USB_HANDLE USBTransferOnePacket(BYTE ep, BYTE dir, BYTE* data, BYTE len); void USBEnableEndpoint(BYTE ep,BYTE options); #if defined(USB_DYNAMIC_EP_CONFIG) void USBInitEP(BYTE ROM* pConfig); #else #define USBInitEP(a) #endif void USBDeviceInit(void); /** CALLBACKS ******************************************************/ void USBCBSuspend(void); void USBCBWakeFromSuspend(void); void USBCB_SOF_Handler(void); void USBCBErrorHandler(void); void USBCBCheckOtherReq(void); void USBCBInitDevClass(void); void USBCBStdSetDscHandler(void); void USBCBSendResume(void); void USBCBInitEP(void);
Komunitas eLearning IlmuKomputer.Com Copyright © 2003-2007 IlmuKomputer.Com
133
//** MACROS ******************************************************/ // Function: BYTE USBHandleBusy(void) #define USBHandleBusy(handle) (handle==0?0:handle->STAT.UOWN) // Function: WORD USBHandleGetLength(void) #define USBHandleGetLength(handle) (handle->CNT) // Function: WORD USBHandleGetAddr(void) #define USBHandleGetAddr(handle) (handle->ADR) // Function: void USBEP0SetSourceRAM(BYTE* src) #define USBEP0SetSourceRAM(src) inPipes[0].pSrc.bRam = src // Function: void USBEP0SetSourceROM(BYTE* src) #define USBEP0SetSourceROM(src) inPipes[0].pSrc.bRom = src // Function: void USBEP0Transmit(BYTE options) #define USBEP0Transmit(options) inPipes[0].info.Val = options | USB_INPIPES_BUSY // Function: void USBEP0SetSize(WORD size) #define USBEP0SetSize(size) inPipes[0].wCount.Val = size // Function: void USBEP0SendRAMPtr(BYTE* src, WORD size, BYTE Options) #define USBEP0SendRAMPtr(src,size,options) {USBEP0SetSourceRAM(src);USBEP0SetSize(size);USBEP0Transmit(options | USB_EP0_RAM);} // Function: void USBEP0SendROMPtr(BYTE* src, WORD size, BYTE Options) #define USBEP0SendROMPtr(src,size,options) {USBEP0SetSourceROM(src);USBEP0SetSize(size);USBEP0Transmit(options | USB_EP0_ROM);} // Function: void USBTxOnePacket(BYTE ep, BYTE* data, WORD len) #define USBTxOnePacket(ep,data,len) USBTransferOnePacket(ep,1,data,len) // Function: void USBRxOnePacket(BYTE ep, BYTE* data, WORD len) #define USBRxOnePacket(ep,data,len) USBTransferOnePacket(ep,0,data,len) // Function: void USBClearInterruptFlag(WORD reg, BYTE flag) void USBClearInterruptFlag(BYTE* reg, BYTE flag); // Function: void USBClearInterruptRegister(WORD reg) #if defined(__18CXX) #define USBClearInterruptRegister(reg) reg = 0; #elif defined(__C30__) #define USBClearInterruptRegister(reg) reg = 0xFF; #endif // Function: void USBStallEndpoint(BYTE ep, BYTE dir) void USBStallEndpoint(BYTE ep, BYTE dir); #if (USB_PING_PONG_MODE == USB_PING_PONG__NO_PING_PONG) #define USB_NEXT_EP0_OUT_PING_PONG 0x0000 // Used in USB Device Mode only #define USB_NEXT_EP0_IN_PING_PONG 0x0000 // Used in USB Device Mode only #define USB_NEXT_PING_PONG 0x0000 // Used in USB Device Mode only #define EP0_OUT_EVEN 0 #define EP0_OUT_ODD 0 #define EP0_IN_EVEN 1 #define EP0_IN_ODD 1 #define EP1_OUT_EVEN 2 #define EP1_OUT_ODD 2 #define EP1_IN_EVEN 3 #define EP1_IN_ODD 3 #define EP2_OUT_EVEN 4 #define EP2_OUT_ODD 4 #define EP2_IN_EVEN 5
Komunitas eLearning IlmuKomputer.Com Copyright © 2003-2007 IlmuKomputer.Com
134
#define EP2_IN_ODD #define EP3_OUT_EVEN #define EP3_OUT_ODD #define EP3_IN_EVEN #define EP3_IN_ODD #define EP4_OUT_EVEN #define EP4_OUT_ODD #define EP4_IN_EVEN #define EP4_IN_ODD #define EP5_OUT_EVEN #define EP5_OUT_ODD #define EP5_IN_EVEN #define EP5_IN_ODD #define EP6_OUT_EVEN #define EP6_OUT_ODD #define EP6_IN_EVEN #define EP6_IN_ODD #define EP7_OUT_EVEN #define EP7_OUT_ODD #define EP7_IN_EVEN #define EP7_IN_ODD #define EP8_OUT_EVEN #define EP8_OUT_ODD #define EP8_IN_EVEN #define EP8_IN_ODD #define EP9_OUT_EVEN #define EP9_OUT_ODD #define EP9_IN_EVEN #define EP9_IN_ODD #define EP10_OUT_EVEN #define EP10_OUT_ODD #define EP10_IN_EVEN #define EP10_IN_ODD #define EP11_OUT_EVEN #define EP11_OUT_ODD #define EP11_IN_EVEN #define EP11_IN_ODD #define EP12_OUT_EVEN #define EP12_OUT_ODD #define EP12_IN_EVEN #define EP12_IN_ODD #define EP13_OUT_EVEN #define EP13_OUT_ODD #define EP13_IN_EVEN #define EP13_IN_ODD #define EP14_OUT_EVEN #define EP14_OUT_ODD #define EP14_IN_EVEN #define EP14_IN_ODD #define EP15_OUT_EVEN #define EP15_OUT_ODD #define EP15_IN_EVEN #define EP15_IN_ODD
5 6 6 7 7 8 8 9 9 10 10 11 11 12 12 13 13 14 14 15 15 16 16 17 17 18 18 19 19 20 20 21 21 22 22 23 23 24 24 25 25 26 26 27 27 28 28 29 29 30 30 31 31
// Used in USB Device Mode only
#define EP(ep,dir,pp) (2*ep+dir) // Used in USB Device Mode only #define BD(ep,dir,pp) ((8 * ep) + (4 * dir)) // Used in USB Device Mode only #elif (USB_PING_PONG_MODE == USB_PING_PONG__EP0_OUT_ONLY) #define USB_NEXT_EP0_OUT_PING_PONG 0x0004 #define USB_NEXT_EP0_IN_PING_PONG 0x0000 #define USB_NEXT_PING_PONG 0x0000 #define EP0_OUT_EVEN 0 #define EP0_OUT_ODD 1 #define EP0_IN_EVEN 2 #define EP0_IN_ODD 2
Komunitas eLearning IlmuKomputer.Com Copyright © 2003-2007 IlmuKomputer.Com
135
#define EP1_OUT_EVEN #define EP1_OUT_ODD #define EP1_IN_EVEN #define EP1_IN_ODD #define EP2_OUT_EVEN #define EP2_OUT_ODD #define EP2_IN_EVEN #define EP2_IN_ODD #define EP3_OUT_EVEN #define EP3_OUT_ODD #define EP3_IN_EVEN #define EP3_IN_ODD #define EP4_OUT_EVEN #define EP4_OUT_ODD #define EP4_IN_EVEN #define EP4_IN_ODD #define EP5_OUT_EVEN #define EP5_OUT_ODD #define EP5_IN_EVEN #define EP5_IN_ODD #define EP6_OUT_EVEN #define EP6_OUT_ODD #define EP6_IN_EVEN #define EP6_IN_ODD #define EP7_OUT_EVEN #define EP7_OUT_ODD #define EP7_IN_EVEN #define EP7_IN_ODD #define EP8_OUT_EVEN #define EP8_OUT_ODD #define EP8_IN_EVEN #define EP8_IN_ODD #define EP9_OUT_EVEN #define EP9_OUT_ODD #define EP9_IN_EVEN #define EP9_IN_ODD #define EP10_OUT_EVEN #define EP10_OUT_ODD #define EP10_IN_EVEN #define EP10_IN_ODD #define EP11_OUT_EVEN #define EP11_OUT_ODD #define EP11_IN_EVEN #define EP11_IN_ODD #define EP12_OUT_EVEN #define EP12_OUT_ODD #define EP12_IN_EVEN #define EP12_IN_ODD #define EP13_OUT_EVEN #define EP13_OUT_ODD #define EP13_IN_EVEN #define EP13_IN_ODD #define EP14_OUT_EVEN #define EP14_OUT_ODD #define EP14_IN_EVEN #define EP14_IN_ODD #define EP15_OUT_EVEN #define EP15_OUT_ODD #define EP15_IN_EVEN #define EP15_IN_ODD
3 3 4 4 5 5 6 6 7 7 8 8 9 9 10 10 11 11 12 12 13 13 14 14 15 15 16 16 17 17 18 18 19 19 20 20 21 21 22 22 23 23 24 24 25 25 26 26 27 27 28 28 29 29 30 30 31 31 32 32
#define EP(ep,dir,pp) (2*ep+dir+(((ep==0)&&(dir==0))?pp:2)) #define BD(ep,dir,pp) (4*(ep+dir+(((ep==0)&&(dir==0))?pp:2)))
Komunitas eLearning IlmuKomputer.Com Copyright © 2003-2007 IlmuKomputer.Com
136
#elif (USB_PING_PONG_MODE == USB_PING_PONG__FULL_PING_PONG) #define USB_NEXT_EP0_OUT_PING_PONG 0x0004 #define USB_NEXT_EP0_IN_PING_PONG 0x0004 #define USB_NEXT_PING_PONG 0x0004 #define EP0_OUT_EVEN 0 #define EP0_OUT_ODD 1 #define EP0_IN_EVEN 2 #define EP0_IN_ODD 3 #define EP1_OUT_EVEN 4 #define EP1_OUT_ODD 5 #define EP1_IN_EVEN 6 #define EP1_IN_ODD 7 #define EP2_OUT_EVEN 8 #define EP2_OUT_ODD 9 #define EP2_IN_EVEN 10 #define EP2_IN_ODD 11 #define EP3_OUT_EVEN 12 #define EP3_OUT_ODD 13 #define EP3_IN_EVEN 14 #define EP3_IN_ODD 15 #define EP4_OUT_EVEN 16 #define EP4_OUT_ODD 17 #define EP4_IN_EVEN 18 #define EP4_IN_ODD 19 #define EP5_OUT_EVEN 20 #define EP5_OUT_ODD 21 #define EP5_IN_EVEN 22 #define EP5_IN_ODD 23 #define EP6_OUT_EVEN 24 #define EP6_OUT_ODD 25 #define EP6_IN_EVEN 26 #define EP6_IN_ODD 27 #define EP7_OUT_EVEN 28 #define EP7_OUT_ODD 29 #define EP7_IN_EVEN 30 #define EP7_IN_ODD 31 #define EP8_OUT_EVEN 32 #define EP8_OUT_ODD 33 #define EP8_IN_EVEN 34 #define EP8_IN_ODD 35 #define EP9_OUT_EVEN 36 #define EP9_OUT_ODD 37 #define EP9_IN_EVEN 38 #define EP9_IN_ODD 39 #define EP10_OUT_EVEN 40 #define EP10_OUT_ODD 41 #define EP10_IN_EVEN 42 #define EP10_IN_ODD 43 #define EP11_OUT_EVEN 44 #define EP11_OUT_ODD 45 #define EP11_IN_EVEN 46 #define EP11_IN_ODD 47 #define EP12_OUT_EVEN 48 #define EP12_OUT_ODD 49 #define EP12_IN_EVEN 50 #define EP12_IN_ODD 51 #define EP13_OUT_EVEN 52 #define EP13_OUT_ODD 53 #define EP13_IN_EVEN 54 #define EP13_IN_ODD 55 #define EP14_OUT_EVEN 56 #define EP14_OUT_ODD 57 #define EP14_IN_EVEN 58 #define EP14_IN_ODD 59
Komunitas eLearning IlmuKomputer.Com Copyright © 2003-2007 IlmuKomputer.Com
137
#define EP15_OUT_EVEN #define EP15_OUT_ODD #define EP15_IN_EVEN #define EP15_IN_ODD
60 61 62 63
#define EP(ep,dir,pp) (4*ep+2*dir+pp) #define BD(ep,dir,pp) (4*(4*ep+2*dir+pp)) #elif (USB_PING_PONG_MODE == USB_PING_PONG__ALL_BUT_EP0) #define USB_NEXT_EP0_OUT_PING_PONG 0x0000 #define USB_NEXT_EP0_IN_PING_PONG 0x0000 #define USB_NEXT_PING_PONG 0x0004 #define EP0_OUT_EVEN 0 #define EP0_OUT_ODD 0 #define EP0_IN_EVEN 1 #define EP0_IN_ODD 1 #define EP1_OUT_EVEN 2 #define EP1_OUT_ODD 3 #define EP1_IN_EVEN 4 #define EP1_IN_ODD 5 #define EP2_OUT_EVEN 6 #define EP2_OUT_ODD 7 #define EP2_IN_EVEN 8 #define EP2_IN_ODD 9 #define EP3_OUT_EVEN 10 #define EP3_OUT_ODD 11 #define EP3_IN_EVEN 12 #define EP3_IN_ODD 13 #define EP4_OUT_EVEN 14 #define EP4_OUT_ODD 15 #define EP4_IN_EVEN 16 #define EP4_IN_ODD 17 #define EP5_OUT_EVEN 18 #define EP5_OUT_ODD 19 #define EP5_IN_EVEN 20 #define EP5_IN_ODD 21 #define EP6_OUT_EVEN 22 #define EP6_OUT_ODD 23 #define EP6_IN_EVEN 24 #define EP6_IN_ODD 25 #define EP7_OUT_EVEN 26 #define EP7_OUT_ODD 27 #define EP7_IN_EVEN 28 #define EP7_IN_ODD 29 #define EP8_OUT_EVEN 30 #define EP8_OUT_ODD 31 #define EP8_IN_EVEN 32 #define EP8_IN_ODD 33 #define EP9_OUT_EVEN 34 #define EP9_OUT_ODD 35 #define EP9_IN_EVEN 36 #define EP9_IN_ODD 37 #define EP10_OUT_EVEN 38 #define EP10_OUT_ODD 39 #define EP10_IN_EVEN 40 #define EP10_IN_ODD 41 #define EP11_OUT_EVEN 42 #define EP11_OUT_ODD 43 #define EP11_IN_EVEN 44 #define EP11_IN_ODD 45 #define EP12_OUT_EVEN 46 #define EP12_OUT_ODD 47 #define EP12_IN_EVEN 48 #define EP12_IN_ODD 49
Komunitas eLearning IlmuKomputer.Com Copyright © 2003-2007 IlmuKomputer.Com
138
#define EP13_OUT_EVEN 50 #define EP13_OUT_ODD 51 #define EP13_IN_EVEN 52 #define EP13_IN_ODD 53 #define EP14_OUT_EVEN 54 #define EP14_OUT_ODD 55 #define EP14_IN_EVEN 56 #define EP14_IN_ODD 57 #define EP15_OUT_EVEN 58 #define EP15_OUT_ODD 59 #define EP15_IN_EVEN 60 #define EP15_IN_ODD 61 #define EP(ep,dir,pp) (4*ep+2*dir+((ep==0)?0:(pp-2))) #define BD(ep,dir,pp) (4*(4*ep+2*dir+((ep==0)?0:(pp-2)))) #else #error "No ping pong mode defined." #endif #endif //USBD_H
14. usb_function_hid.h (C:\HID_ku\Header) /******************************************************************************* USB HID class header file FileName: usb_function_hid.h (c) Microchip Technology, Inc. *******************************************************************/ #ifndef HID_H #define HID_H /* Class-Specific Requests */ #define GET_REPORT 0x01 #define GET_IDLE 0x02 #define GET_PROTOCOL 0x03 #define SET_REPORT 0x09 #define SET_IDLE 0x0A #define SET_PROTOCOL 0x0B /* Class Descriptor Types */ #define DSC_HID #define DSC_RPT #define DSC_PHY
0x21 0x22 0x23
/* Protocol Selection */ #define BOOT_PROTOCOL #define RPT_PROTOCOL
0x00 0x01
/* HID Interface Class Code */ #define HID_INTF /* HID Interface Class SubClass Codes */ #define BOOT_INTF_SUBCLASS
0x03 0x01
/* HID Interface Class Protocol Codes */ #define HID_PROTOCOL_NONE #define HID_PROTOCOL_KEYBOAD #define HID_PROTOCOL_MOUSE
0x00 0x01 0x02
// Function: BOOL mHIDRxIsBusy(void) #define mHIDRxIsBusy() EPTable[HID_BD_OUT].Stat.UOWN // Function: BOOL mHIDTxIsBusy(void) #define mHIDTxIsBusy() EPTable[HID_BD_IN].Stat.UOWN // Macro:
BYTE mHIDGetRptRxLength(void)
Komunitas eLearning IlmuKomputer.Com Copyright © 2003-2007 IlmuKomputer.Com
139
#define mHIDGetRptRxLength() hid_rpt_rx_len #define HIDTxHandleBusy USBHandleBusy #define HIDRxHandleBusy USBHandleBusy #define HIDTxPacket USBTxOnePacket #define HIDRxPacket USBRxOnePacket typedef struct _USB_HID_DSC_HEADER { BYTE bDescriptorType; //offset 9 WORD wDscLength; //offset 10 } USB_HID_DSC_HEADER; typedef struct _USB_HID_DSC { BYTE bLength; BYTE bDescriptorType; WORD bcdHID; BYTE bCountryCode; BYTE bNumDsc;
//offset 0 //offset 1 //offset 2 //offset 4 //offset 5
} USB_HID_DSC; /** EXTERNS ********************************************************/ extern BYTE hid_rpt_rx_len; /** PUBLIC PROTOTYPES **********************************************/ #if defined(USB_DYNAMIC_EP_CONFIG) #define HIDInitEP() #else // Function: void HIDInitEP(void) void HIDInitEP(void); #endif // Function: void USBCheckHIDRequest(void) void USBCheckHIDRequest(void); #endif //HID_H
15. usb_hal.h (C:\HID_ku\Header) /****************************************************************************** USB Hardware Abstraction Layer (HAL) (Header File) Filename: usb_hal.h (c) Microchip Technology, Inc. *************************************************************************/ #ifndef _USB_HAL_H_ #define _USB_HAL_H_ //DOM-IGNORE-END #if defined(USB_SUPPORT_HOST) || defined(USB_SUPORT_OTG) /******************************************************************** Interface Routines Function: USBHALSetBusAddress *************************************************************************/ #define USBHALSetBusAddress OTGCORE_SetDeviceAddr void USBHALSetBusAddress( BYTE addr ); /************************************************************************* Function: USBHALControlUsbResistors *************************************************************************/ #if defined(__18CXX) //TODO: (DF) - better solution here? void USBHALControlUsbResistors( BYTE flags );
Komunitas eLearning IlmuKomputer.Com Copyright © 2003-2007 IlmuKomputer.Com
140
#else #define USBHALControlUsbResistors OTGCORE_ControlUsbResistors void USBHALControlUsbResistors( BYTE flags ); #endif /* USBHALControlUsbResistors flags */ #define USB_HAL_PULL_UP_D_PLUS 0x80 #define USB_HAL_PULL_UP_D_MINUS 0x40 #define USB_HAL_PULL_DN_D_PLUS 0x20 #define USB_HAL_PULL_DN_D_MINUS 0x10 // The following are defined for convenience: #define USB_HAL_DEV_CONN_FULL_SPD #define USB_HAL_DEV_CONN_LOW_SPD #define USB_HAL_DEV_DISCONNECT
// Pull D+ line high // Pull D- line high // Pull D+ line low // Pull D- line low USB_HAL_PULL_UP_D_PLUS USB_HAL_PULL_UP_D_MINUS 0
// To Do: Define a method to check for SE0 & a way to send a reset (SE0). /************************************************************************* Function: USBHALSessionIsValid *************************************************************************/ BOOL USBHALSessionIsValid( void ); /************************************************************************* Function: USBHALControlBusPower *************************************************************************/ BOOL USBHALControlBusPower( BYTE cmd ); /* USBHALControlBusPower Commands */ #define USB_VBUS_DISCHARGE 0 // Dicharge Vbus via resistor #define USB_VBUS_CHARGE 1 // Charge Vbus via resistor #define USB_VBUS_POWER_ON 3 // Supply power to Vbus #define USB_VBUS_POWER_OFF 4 // Do not supply power to Vbus /************************************************************************* Function: USBHALGetLastError *************************************************************************/ unsigned long USBHALGetLastError( void ); // USBHALGetLastError Error Bits. #define USBHAL_PID_ERR 0x00000001 // Packet ID Error #define USBHAL_CRC5 0x00000002 // (Host) Token CRC5 check failed #define USBHAL_HOST_EOF 0x00000002 // (Host) EOF not reached before next SOF #define USBHAL_CRC16 0x00000004 // Data packet CRC error #define USBHAL_DFN8 0x00000008 // Data field size not n*8 bits #define USBHAL_BTO_ERR 0x00000010 // Bus turn-around timeout #define USBHAL_DMA_ERR 0x00000020 // DMA error, unable to read/write memory #define USBHAL_BTS_ERR 0x00000080 // Bit-stuffing error #define USBHAL_XFER_ID 0x00000100 // Unable to identify transfer EP #define USBHAL_NO_EP 0x00000200 // Invalid endpoint number #define USBHAL_DMA_ERR2 0x00000400 // Error starting DMA transaction /************************************************************************* Function: USBHALHandleBusEvent *************************************************************************/ void USBHALHandleBusEvent ( void ); /************************************************************************* Function: USBHALStallPipe *************************************************************************/ #define USBHALStallPipe OTGCORE_StallPipe BOOL USBHALStallPipe( TRANSFER_FLAGS pipe ); /****************************************************************************** Function: OTGCORE_UnstallPipe *****************************************************************************/ #define USBHALUnstallPipe OTGCORE_UnstallPipe
Komunitas eLearning IlmuKomputer.Com Copyright © 2003-2007 IlmuKomputer.Com
141
BOOL USBHALUnstallPipe( TRANSFER_FLAGS pipe ); // Function: USBHALGetStalledEndpoints #define USBHALGetStalledEndpoints OTGCORE_GetStalledEndpoints UINT16 USBHALGetStalledEndpoints ( void ); // Function: USBHALFlushPipe *****************************************************************************/ BOOL USBHALFlushPipe( TRANSFER_FLAGS pipe ); /************************************************************************* Function: USBHALTransferData *************************************************************************/ BOOL USBHALTransferData ( TRANSFER_FLAGS flags, void *buffer, unsigned int size ); /**************************************************************** Function: USBHALSetEpConfiguration ***************************************************************/ BOOL USBHALSetEpConfiguration ( BYTE ep_num, UINT16 max_pkt_size, UINT16 flags ); /* Flags for USBHALSetEpConfiguration */ #if defined(__18CXX) #define USB_HAL_TRANSMIT 0x0400 // Enable EP for transmitting data #define USB_HAL_RECEIVE 0x0200 // Enable EP for receiving data #define USB_HAL_HANDSHAKE 0x1000 // Enable EP to give ACK/NACK (non isoch) #define USB_HAL_NO_INC 0x0010 // Use for DMA to another device FIFO #define USB_HAL_HW_KEEPS 0x0020 // Cause HW to keep EP #else #define USB_HAL_TRANSMIT 0x0400 // Enable EP for transmitting data #define USB_HAL_RECEIVE 0x0800 // Enable EP for receiving data #define USB_HAL_HANDSHAKE 0x0100 // Enable EP to give ACK/NACK (non isoch) /* Does not work, Fix this if needed. 3/1/07 - Bud #define USB_HAL_NO_INC 0x0010 // Use for DMA to another device FIFO #define USB_HAL_HW_KEEPS 0x0020 // Cause HW to keep EP */ #define USB_HAL_ALLOW_HUB 0x8000 // (host only) Enable low-spd hub support #define USB_HAL_NO_RETRY 0x4000 // (host only) disable auto-retry on NACK #endif /************************************************************************* Function: USBHALInitialize *************************************************************************/ BOOL USBHALInitialize ( unsigned long flags ); #else // defined(USB_SUPPORT_HOST) || defined(USB_SUPORT_OTG) #if defined(__18CXX) #include "header\usb_hal_pic18.h" #elif defined(__C30__) #include "header\usb_hal_pic24.h" #endif #endif // defined(USB_SUPPORT_HOST) || defined(USB_SUPORT_OTG) #endif // _USB_HAL_H_ /************************************************************************* * EOF */
16. usb_hal_pic18.h (C:\HID_ku\Header) /****************************************************************************** USB Hardware Abstraction Layer (HAL) (Header File) Filename: usb_hal_pic18.h
Komunitas eLearning IlmuKomputer.Com Copyright © 2003-2007 IlmuKomputer.Com
142
(c) Microchip Technology, Inc. ****************************************************************/ #define USBPowerModule() //* Function: USBSetBDTAddress(addr) #define USBSetBDTAddress(addr) #define USBPingPongBufferReset UCONbits.PPBRST #define USBTransactionCompleteIE UIEbits.TRNIE #define USBTransactionCompleteIF UIRbits.TRNIF #define USBTransactionCompleteIFReg (BYTE*)&UIR #define USBTransactionCompleteIFBitNum 3 #define USBResetIE UIEbits.URSTIE #define USBResetIF UIRbits.URSTIF #define USBResetIFReg (BYTE*)&UIR #define USBResetIFBitNum 0 #define USBIdleIE UIEbits.IDLEIE #define USBIdleIF UIRbits.IDLEIF #define USBIdleIFReg (BYTE*)&UIR #define USBIdleIFBitNum 4 #define USBActivityIE UIEbits.ACTVIE #define USBActivityIF UIRbits.ACTVIF #define USBActivityIFReg (BYTE*)&UIR #define USBActivityIFBitNum 2 #define USBSOFIE UIEbits.SOFIE #define USBSOFIF UIRbits.SOFIF #define USBSOFIFReg (BYTE*)&UIR #define USBSOFIFBitNum 6 #define USBStallIE UIEbits.STALLIE #define USBStallIF UIRbits.STALLIF #define USBStallIFReg (BYTE*)&UIR #define USBStallIFBitNum 5 #define USBErrorIE UIEbits.UERRIE #define USBErrorIF UIRbits.UERRIF #define USBErrorIFReg (BYTE*)&UIR #define USBErrorIFBitNum 1 #define USBSE0Event UCONbits.SE0 #define USBSuspendControl UCONbits.SUSPND #define USBPacketDisable UCONbits.PKTDIS #define USBResumeControl UCONbits.RESUME /* Buffer Descriptor Status Register Initialization Parameters */ #define _BSTALL 0x04 //Buffer Stall enable #define _DTSEN 0x08 //Data Toggle Synch enable #define _INCDIS 0x10 //Address increment disable #define _KEN 0x20 //SIE keeps buff descriptors enable #define _DAT0 0x00 //DATA0 packet expected next #define _DAT1 0x40 //DATA1 packet expected next #define _DTSMASK 0x40 //DTS Mask #define _USIE 0x80 //SIE owns buffer #define _UCPU 0x00 //CPU owns buffer #define _STAT_MASK 0xFF /* BDT entry structure definition */ typedef union _BD_STAT { BYTE Val;
Komunitas eLearning IlmuKomputer.Com Copyright © 2003-2007 IlmuKomputer.Com
143
struct{ //If the CPU owns the buffer then these are the values unsigned BC8:1; //bit 8 of the byte count unsigned BC9:1; //bit 9 of the byte count unsigned BSTALL:1; //Buffer Stall Enable unsigned DTSEN:1; //Data Toggle Synch Enable unsigned INCDIS:1; //Address Increment Disable unsigned KEN:1; //BD Keep Enable unsigned DTS:1; //Data Toggle Synch Value unsigned UOWN:1; //USB Ownership }; struct{ unsigned BC8:1; //bit 8 of the byte count unsigned BC9:1; //bit 9 of the byte count unsigned PID0:1; //Packet Identifier unsigned PID1:1; unsigned PID2:1; unsigned PID3:1; unsigned :1; unsigned UOWN:1; //USB Ownership }; struct{ unsigned :2; unsigned PID:4; //Packet Identifier unsigned :2; }; } BD_STAT; //Buffer Descriptor Status Register typedef union __BDT { struct { BD_STAT STAT; BYTE CNT; BYTE ADRL; BYTE ADRH; }; struct { unsigned :8; unsigned :8; BYTE* ADR; }; DWORD Val; BYTE v[4]; } BDT_ENTRY; #define USTAT_EP0_PP_MASK #define USTAT_EP_MASK #define USTAT_EP0_OUT #define USTAT_EP0_OUT_EVEN #define USTAT_EP0_OUT_ODD #define USTAT_EP0_IN #define USTAT_EP0_IN_EVEN #define USTAT_EP0_IN_ODD
//Buffer Address Low //Buffer Address High
//Buffer Address
~0x02 0x7E 0x00 0x00 0x02 0x04 0x04 0x06
typedef union { WORD UEP[16]; } _UEP; #define UEP_STALL #define USB_BDT_ADDRESS
0x0001 0x400
Komunitas eLearning IlmuKomputer.Com Copyright © 2003-2007 IlmuKomputer.Com
144
#define USB_VOLATILE
17. rm18f4550.lkr (C:\HID_ku\Linker) // FileName: rm18f4550.lkr // Sample linker command file for 18F4550 with Bootloader LIBPATH . FILES c018i.o FILES clib.lib FILES p18f4550.lib CODEPAGE CODEPAGE CODEPAGE CODEPAGE CODEPAGE CODEPAGE CODEPAGE
NAME=boot NAME=vectors NAME=page NAME=idlocs NAME=config NAME=devid NAME=eedata
START=0x0 START=0x800 START=0x82A START=0x200000 START=0x300000 START=0x3FFFFE START=0xF00000
ACCESSBANK NAME=accessram START=0x0 DATABANK NAME=gpr0 START=0x60 DATABANK NAME=gpr1 START=0x100 DATABANK NAME=gpr2 START=0x200 DATABANK NAME=gpr3 START=0x300 DATABANK NAME=usb4 START=0x400 DATABANK NAME=usb5 START=0x500 DATABANK NAME=usb6 START=0x600 DATABANK NAME=usb7 START=0x700 ACCESSBANK NAME=accesssfr START=0xF60 SECTION
NAME=CONFIG
END=0x7FF END=0x0x829 END=0x7FFF END=0x200007 END=0x30000D END=0x3FFFFF END=0xF000FF
PROTECTED PROTECTED PROTECTED PROTECTED PROTECTED PROTECTED
END=0x5F END=0xFF END=0x1FF END=0x2FF END=0x3FF END=0x4FF END=0x5FF END=0x6FF END=0x7FF END=0xFFF
PROTECTED PROTECTED PROTECTED PROTECTED PROTECTED
ROM=config
STACK SIZE=0x100 RAM=gpr3
Jika semua program telah menjadi satu dalam satu project HID_ku, pada MPLAB IDE lakukan kompile dengan cara : Project> Build All >.... Project yang berhasil akan nampak seperti Gambar 5.4.
Gambar 5.4. Hasil kompile program dengan MPLAB IDE
Secara garis besar sistem firmware yang ada di PIC18F4550 terdiri dari 3 buah bagian seperti Gambar 5.2.
Komunitas eLearning IlmuKomputer.Com Copyright © 2003-2007 IlmuKomputer.Com
145
InitializeSystem
USBDeviceTask
ProcessIO
Gambar 5.5. Urutan aplikasi pada Microchip Framework versi 2.1
Pertama kali device dideteksi oleh host, device akan menginisialisasi diri dengan program InitializeSystem. Di dalam rutin inilah inisialisasi semua interrupt, dan konfigurasi pin Input dan Output dilakukan. Selain itu pada fungsi UsbDeviceInit (file usb_device.c) akan mereset semua error yang terjadi, termasuk semua register. Pada saat ini kondisi device adalah DEATTACHED. Rutin USBDeviceTask akan membuat kondisi DEATTACHED menjadi ATTACH. Pada saat ini Device masuk ke transfer interrupt. Ada 3 interrupt yang harus ditangani oleh rutin ini yaitu interrupt aktivitas USB, Aktivitas Reset Bus USB, dan melayani interupsi yang lain. Komunikasi interrupt kelas HID terdapat dalam rutin USBDeviceTask dan dalam rutin ini juga tidak boleh terputus. Selain itu, pemanggilannya dilakukan secara priodik, tergantung dari kemampuan dan desain kerja host. Pemanggilan rutin ini dilakukan oleh host, nilai timer pada aplikasi host menentukan seberapa sering pemanggilan USBDeviceTask per mili detiknya. Jika kondisi device terakhir kali dideteksi ATTACH, maka dalam rutin USBDeviceTask akan dibuat SUSPEND lagi, dan selajutnya menunggu interupsi untuk masuk ke proses IO. Proses IO merupakan proses dimana aplikasi yang akan kita bangun akan berhubungan dengan port dan segala macam fungsi USB diletakkan, termasuk pembacaan ADC, nilai Port B dan keluaran Port D. Proses IO ini juga merupakan sebuah fungsi LoopBack yang melakukan perulangan secara periodik. Jika rutin program yang berhubungan dengan fungsi mikrokontroler selesai, device masuk ke mode SUSPEND dan kembali melakukan pooling pada rutin USBDeviceTask. Apabila ditengah jalan terdapat kesalahan dalam pengiriman data, maka rutin USBDeviceTask akan mengembalikan posisi device ke mode ATTACH.
MENDOWNLOAD FILE HEX KE PIC 18F4550 Semua program yang telah dibangun tersebut berjalan di atas program bootload. Jika kondisi PIC sudah masuk bootload (update mode) terpenuhi, maka PIC akan memasuki update firmware dan setelah reset ditekan, akan masuk ke mode user kembali. Proses memasuki update mode sama seprti bab ke 10 yaitu dengan menekan tombol BOOT dilanjutkan tombol RESET. Setelah Port D0 dan Port D1 dalam kondisi blink, aplikasi PICDEM FS USB Demo Tool akan mampu mendeteksi keberadaan update mode PIC18F4550.
Komunitas eLearning IlmuKomputer.Com Copyright © 2003-2007 IlmuKomputer.Com
146
Gambar 5.6. PICDEM USB Tool dan pemilihan HID_ku.hex untuk di upload ke PIC
Gambar 5.7. Jendela pilihan settingan board (Pilih “No”)
Pilih file yang akan di download (Gambar 5.16). Pilih HID_ku yang ada di directory :C:\HID_ku\. Akan muncul peringatan bahwa antara settingan board dan data HID_ku mempunyai konfigurasi yang berbeda (Gambar 5.7). Abaikan dengan mengklik “No”. Selanjutnya balik ke menu awal, pilih tombol “Program Device”. Setelah selesai, tekan tombol RESET pada rangkaian, kini PIC 18F4550 sudah masuk ke user mode dan siap diaplikasikan dengan kelas HID.
DRIVER
UNTUK APLIKASI HOST
Seperti halnya standar Human Interface Device, Windows dengan sendirinya akan mendeteksi jenis report device yang terhubung. Jika diketahui merupakan device baru, maka resgistry di Windows akan segera merekam keberadaan device tersebut, dan menentukan jenis konfigurasi yang sesuai. Setelah tombol RESET pada rangkaian bootload kita tekan, maka PIC18F4550 akan memasuki user mode. Pada Device Manager (Windows XP) akan segera dideteksi keberadaan device baru yang berada di bawah hirarki kelas Human Interface Device. Kita dapat melihat properti yang ada, termasuk nilai Product dan Vendor ID device yang kita program. Descriptor string “Data Vision” akan muncul, selanjutnya pengguna tidak akan disuguhi jendela untuk memilih driver, sebab Windows sudah mendeteksi dan menempatkan driver untuk kelas HID (Gambar 5.8).
Komunitas eLearning IlmuKomputer.Com Copyright © 2003-2007 IlmuKomputer.Com
147
Gambar 5.8. Deteksi Device pada Device Manager Windows XP
Gambar 5.9. Nilai Properti Dari Device (Ms Windows XP)
Banyak tool software yang dapat digunakan untuk menganalisa dan memanipulasi report HID. Salah satunya adalah HIDTester yang dibuat oleh Lake View Research (www.lvr.com) yang dapat menganalisa penggunaan Hid API.
Gambar 5.10. Analisa dengan HID Device Tester
Dengan menggunakan HIDTester kita dapat secara langsung melihat jenis HID yang sedang terhubung ke komputer (lihat Gambar 5.10). Pada HIDTester terlihat bahwa Product String yakni “HID PIC18F4550” langsung terdeteksi. Dengan tool ini kita juga bisa melihat dan melakukan tes standar maupun extra test pemrograman USB khusus untuk HID. Klik pada tombol Basic Test Komunitas eLearning IlmuKomputer.Com Copyright © 2003-2007 IlmuKomputer.Com
148
atau pada Extended Test maka kita dapat melihat perintah HidD_GetPrephasedData sampai HidD String. HIDTester hanya mempunyai fasilitas untuk mengetes perintah–perintah dasar kelas HID. Lain halnya dengan HID Simple Write yang memungkinkan kita menggunakan test menulis ke device dengan catatan device mempunyai report output (dari sisi device merupakan input) yang lebih dari satu. Ketika kita menjalankan program HID Simple Write, setelah device tersambung, kita bisa melihat identifikasi device secara detail (Gambar 5.11). Klik tombol info maka akan didapatkan keterangan mengenai device yang bersangkutan. Kita bisa menulis kode report out di dalam jendela label yang ada di paling bawah. (pada Gambar 5.11 terlihat misalnya kita menuliskan nilai 00 01 hexa). Lalu kita klik tombol Write maka report input akan muncul dan data yang tersaji akan muncul dalam jendela. Dengan demikian untuk mengetes bagaimana komunikasi yang sedang berjalan pada device dapat dilakukan sebelum kita mendesain aplikasi host. Jika menggunakan SimpleHIDWrite sudah berjalan sesuai dengan desain komunikasi yang kita buat, baruah kita mendesain aplikasi host dan memikirkan bagaimana GUI (Graphical User Interface) yang menarik untuk pengguna aplikasi kita (end user).
Gambar 5.11. Keterangan device pada HID Device Tool
PROGRAMMING HOST DENGAN VB 6 Programming Host pada aplikasi antarmuka kelas HID tidak mungkin lepas dari sebuah Globally Unique Identifier (GUID) yang berisi nilai 128 bit tentang identitas sebuah kelas atau entitas device. Windows menggunakan GUID untuk mengidentifikasi 2 jenis kelas device : Kelas Setup Device dan Kelas Interface Device. Kelas Setup mengarahkan Windows untuk mengalokasikan jenis driver yang sesuai dengan device, dan kelas Interface berfungsi untuk mengatur komunikasi antara driver terpilih dengan device. Dalam tingkat aplikasi, pemrograman VB untuk mendukung kelas HID berbeda dengan emulating serial over USB. Kelas HID membutuhkan rutin pengolahan yang berupa fungsi-fungsi dan prosedur pemrograman untuk Windows API (Application Programming Interface). Windows API untuk HID menyediakan beberapa fungsi untuk membaca dan mengidentifikasi report HID serta mengirim dan menerima report. 1. Menyiapkan permintaan Host mengenai HID device Fungsi HidD_GetPreparseData adalah mendapatkan petunjuk informasi mengenai report dalam sebuh pointer. HidP-GetCaps menggunakan pointer tersebut untuk membaca struktur HIDP_CAPS yang berisi jenis report yang didukung device dan menyediakan informasi mengenai Komunitas eLearning IlmuKomputer.Com Copyright © 2003-2007 IlmuKomputer.Com
149
report yang bersangkutan. Nama dan fungsi HID API saling bersesuaian. Misalnya HidD_FreePreparsedData bertujuan untuk menyiapkan sumber data yang digunakan oleh HidD_GetPreparsedData. Tabel 5.3. berikut merupakan daftar fungsi API yang mengandung permintaan report dalam sebuah komunikasi HID. Daftar fungsi HID API Ms Windows (XP) Kegunaan Phrase fungsi API HID HidD_FreePreparsedData HidD_GetPhysicalDescriptor HidD_GetPreparsedData HidP_GetButtonCaps HidP_GetCaps HidP_GetExtendedAttributes HidP_GetLinkCollectionNodes Untuk mendapatkan info tetang jenis HID dan HidP_GetSpecificButtonCaps jenis report HidP_GetSpecificValueCaps HidP_GetValueCaps HidP_IsSameUsageAndPage HidP_MaxDataListLength HidP_MaxUsageListLength HidP_TranslateUsagesToI8042 HidP_UsageAndPageListDifference HidP_UsageListDifference HidD_GetIndexedString HidD_GetManufacturerString Untuk menerima string dari sebuah HID HidD_GetProductString HidD_GetSerialNumberString HidD_GetFeature HidD_GetInputReport HidD_SetFeature Untuk menerima dan mengirim report HidD_SetOutputReport ReadFile WriteFile HidP_GetButtons HidP_GetButtonsEx HidP_GetData Retrieve HidP_GetScaledUsageValue HidP_GetUsagesEx HidP_GetUsageValue HidP_GetUsageValueArray Untuk memperoleh informasi pada report yang HidP_InitializeReportForID diterima dan menyimpan informasi pada report HidP_SetButtons yang akan dikirim. HidP_SetData HidP_SetScaledUsage HidP_SetUsages Set HidP_SetUsageValue HidP_SetUsageValueArray HidP_UnsetButtons HidP_UnsetUsages HidD_FlushQueue Untuk mengatur komunikasi HID HidD_GetHidGuid Retrieve Komunitas eLearning IlmuKomputer.Com Copyright © 2003-2007 IlmuKomputer.Com
150
Daftar fungsi HID API Ms Windows (XP) Kegunaan Phrase fungsi API HID HidD_GetNumInputBuffers HidD_SetNumInputBuffers HidRegisterMinidriver Tabel 5.3. Daftar fungsi HID
2.
Mengirim dan menerima report Driver pada Windows akan menyuruh kontroler host untuk meminta report Input secara periodik/terus menerus. Driver akan menyimpan report ke dalam buffer, lalu ReadFile akan membaca report yang ada di buffer. Jika buffer sudah kosong, ReadFile akan menunggu untuk kedatangan report. WriteFile berfungsi untuk mengirimkan report Output ke HID. WriteFile menggunakan jalur endpoint transfer interrupt jika HID mempuyai endpoint interrupt OUT. Sebaliknya jika tidak mempunyai, maka WriteFile menggunakan transfer kontrol dengan permintaan Set_report. Jika menggunakan transfer interrupt, WriteFile akan menunggu sampai ada sintak NAK dari device. Jika menggunakan transfer kontrol, WriteFile akan mengebalikan dengan kode error kesalahan atau waktu habis. Untuk mendapatkan report aplikasi (berisi data yang akan diolah), dapat menggunakan data mentah langsung dari buffer atau menggunakan fungsi API untuk mengekstrak nilai byte data. Pada saat yang sama, aplikasi host dapat menulis data untuk dikirim secara langsung ke buffer report atau menggunakan fungsi API untuk meletakkan data yang akan dikirimkan. Pengaturan komunikasi HID dilakukan dengan menggunakan HidD_getHidGuid agar mendapat interface GUID untuk kelas HID. Perintah hidD_SetNumInputBuffers memungkinkan aplikasi mengubah ukuran buffer pada driver HID untuk report input. Nilai buffer yang besar akan membantu jika aplikasi sibuk membaca report sebelum buffer penuh. Namun demikian penggunaan buffer alangkah baiknya disesuaikan dengan banyaknya data yang dibutuhkan.
3.
Mengidentifikasi Device Identifikasi device oleh aplikasi host dapat dilakukan dengan mendeteksi nilai Vendor ID dan Product ID atau mencari kegunaan khusus dari device seperti game controller, keyboard. Untuk beberapa vendor yang tidak mempunyai standar pemakaian, maka pembacaan Product ID dan Vendor ID menjadi hal yang mutlak dilakukan. Fungsi API HidD_getAttributes adalah untuk mendapatkan nilai pointer dari VendorID, ProductID dan nomor rilis device.
4.
Menulis dan membaca report ke device Setelah proses penemuan dan identifikasi device oleh aplikasi host berjalan, proses selanjutnya adalah pertukaran report antara host dan device. Deklarasi dari fungsi WriteFile dalam bahasa Basic (VB 6) adalah sebagai berikut : Function WriteFile _ (ByVal hFile As Integer, _ ByRef lpBuffer As Byte, _ ByVal nNumberOfBytesToWrite As Integer, _ ByRef lpNumberOfBytesWritten As Integer, _ ByVal lpOverlapped As Integer) _
Komunitas eLearning IlmuKomputer.Com Copyright © 2003-2007 IlmuKomputer.Com
151
As Boolean End Function
Sedangkan kode untuk mengirimkan report Output ke HID: Dim NumberOfBytesWritten As Integer Dim OutputReportBuffer() As Byte Dim ReportID as Integer Dim Result as Boolean ReDim OutputReportBuffer _ (Capabilities.OutputReportByteLength - 1) ReportID = 0 OutputReportBuffer(0) = ReportID OutputReportBuffer(1) = 79 ‘contoh OutputReportBuffer(2) = 75 ‘contoh Result = WriteFile _ (DeviceHandle, _ OutputReportBuffer(0), _ UBound(OutputReportBuffer) + 1, _ NumberOfBytesWritten, _ 0)
Parameter lpBuffer menunjuk ke buffer yang mengandung report. Sedangkan nNumberOfBytesToWrite menunjukkan berapa banyak byte yang harus ditulis dan harus sama dengan OutputReportBytelength. Buffer sendiri harus cukup lebar untuk menangani ReportID dan report Data. Fungsi WriteFile akan mengembalikan nilai True dengan NumberofBytesWritten berisi jumlah byte yang berhasil ditulis ke dalam HID. Pada waktu mengirimkan report ke endpoint interrupt, apabila respon balik berupa NAK, maka WriteFile akan menunggu sampai ada ACK dari endpoint. Pada waktu report melalui endpoint kontrol, WriteFile akan menghasilkan kode sukses, error atau timeout. Kemungkinan error yang dikembalikan oleh WriteFile adalah CDC Error. Error ini mengindikasikan bahwa kontroler host berusaha mengirim report, namun device tidak merespon sesuai dengan yang diharapkan. Kebalikan dari WriteFile adalah ReadFile. Pada waktu aplikasi mengatur interface HID dan mengetahui jumlah byte pada report Input device, sehingga aplikasi dapat menggunakan ReadFile untuk membaca report Input dari device. Untuk membaca report yang datang, aplikasi mendeklarasikan sebuah buffer/variable untuk menyimpan data dan memanggil ReadFile. Besarnya buffer harus sama dengan nilai InputReportByteLength. Nilai tersebut diperoleh dari properti HIDP_CAPS, dengan perintah HidP_GetCaps. Jika aplikasi memanggil ReadFile ketika HID membaca nahwa buffer kosong, aplikasi akan menunggu sampai ada report di dalam buffer, atau even dari pengguna yang menutup aplikasi melalui task manager, ataupun karena device yang bersangkutan dicabut dari sistem. Ada beberapa pendekatan untuk mencegah aplikasi “hang” dan menunggu report. Salah satu caranya device mengirimkan report secara terus menerus. Dari sisi host aplikasi, Host dapat mencoba untuk membaca report hanya setelah meminta salah satu report output atau feature. Salah satu jalan meningkatkan performa aplikasi membaca report input adalah meletakkan rutin ReadFile pada tread terpisah yang mampu memberi tahu program utama jika report telah tersedia. Apabila aplikasi akan disudahi, maka komunikasi dengan device harus diputus. Aplikasi harus mampu memanggil rutin CloseHandle untuk menutup beberapa rutin yang dibuka oleh CreateFile. Apabila selesai menggunakan buffer PreparseData yang dikembalikan oleh HidD_GetPreparseData, aplikasi harus memanggil HidD_FreePreparseData. Dalam pemrograman VB 6 untuk aplikasi mengendalikan PIC18F4550, pertama-tama deklarasikan WinAPI untuk HID sesuai dengan sebuah modul terpisah dari form. Modul ini dapat diunduh di www.lvr.com. Komunitas eLearning IlmuKomputer.Com Copyright © 2003-2007 IlmuKomputer.Com
152
Gambar 5.12. Jendela Project
Berilah nama modul yang dibuat dengan nama ApiDeclarations.bas. Script kode modul ini adalah sebagai berikut: '(c)www.lvr.com '****************************************************************************** 'API constants, listed alphabetically '****************************************************************************** 'from setupapi.h Public Const DIGCF_PRESENT = &H2 Public Const DIGCF_DEVICEINTERFACE = &H10 Public Const FILE_FLAG_OVERLAPPED = &H40000000 Public Const FILE_SHARE_READ = &H1 Public Const FILE_SHARE_WRITE = &H2 Public Const FORMAT_MESSAGE_FROM_SYSTEM = &H1000 Public Const GENERIC_READ = &H80000000 Public Const GENERIC_WRITE = &H40000000 'Typedef enum defines a set of integer constants for HidP_Report_Type 'Remember to declare these as integers (16 bits) Public Const HidP_Input = 0 Public Const HidP_Output = 1 Public Const HidP_Feature = 2 Public Const OPEN_EXISTING = 3 Public Const WAIT_TIMEOUT = &H102& Public Const WAIT_OBJECT_0 = 0 '****************************************************************************** 'User-defined types for API calls, listed alphabetically '****************************************************************************** Public Type GUID Data1 As Long Data2 As Integer Data3 As Integer Data4(7) As Byte End Type Public Type HIDD_ATTRIBUTES Size As Long VendorID As Integer ProductID As Integer
Komunitas eLearning IlmuKomputer.Com Copyright © 2003-2007 IlmuKomputer.Com
153
VersionNumber As Integer End Type 'Windows 98 DDK documentation is incomplete. 'Use the structure defined in hidpi.h Public Type HIDP_CAPS Usage As Integer UsagePage As Integer InputReportByteLength As Integer OutputReportByteLength As Integer FeatureReportByteLength As Integer Reserved(16) As Integer NumberLinkCollectionNodes As Integer NumberInputButtonCaps As Integer NumberInputValueCaps As Integer NumberInputDataIndices As Integer NumberOutputButtonCaps As Integer NumberOutputValueCaps As Integer NumberOutputDataIndices As Integer NumberFeatureButtonCaps As Integer NumberFeatureValueCaps As Integer NumberFeatureDataIndices As Integer End Type 'If IsRange is false, UsageMin is the Usage and UsageMax is unused. 'If IsStringRange is false, StringMin is the string index and StringMax is unused. 'If IsDesignatorRange is false, DesignatorMin is the designator index and ‘DesignatorMax is unused. Public Type HidP_Value_Caps UsagePage As Integer ReportID As Byte IsAlias As Long BitField As Integer LinkCollection As Integer LinkUsage As Integer LinkUsagePage As Integer IsRange As Long IsStringRange As Long IsDesignatorRange As Long IsAbsolute As Long HasNull As Long Reserved As Byte BitSize As Integer ReportCount As Integer Reserved2 As Integer Reserved3 As Integer Reserved4 As Integer Reserved5 As Integer Reserved6 As Integer LogicalMin As Long LogicalMax As Long PhysicalMin As Long PhysicalMax As Long UsageMin As Integer UsageMax As Integer StringMin As Integer StringMax As Integer DesignatorMin As Integer DesignatorMax As Integer DataIndexMin As Integer DataIndexMax As Integer End Type Public Type OVERLAPPED Internal As Long
Komunitas eLearning IlmuKomputer.Com Copyright © 2003-2007 IlmuKomputer.Com
154
InternalHigh As Long Offset As Long OffsetHigh As Long hEvent As Long End Type Public Type SECURITY_ATTRIBUTES nLength As Long lpSecurityDescriptor As Long bInheritHandle As Long End Type Public Type SP_DEVICE_INTERFACE_DATA cbSize As Long InterfaceClassGuid As GUID Flags As Long Reserved As Long End Type Public Type SP_DEVICE_INTERFACE_DETAIL_DATA cbSize As Long DevicePath As Byte End Type Public Type SP_DEVINFO_DATA cbSize As Long ClassGuid As GUID DevInst As Long Reserved As Long End Type '****************************************************************************** 'API functions, listed alphabetically '****************************************************************************** Public Declare Function CancelIo _ Lib "kernel32" _ (ByVal hFile As Long) _ As Long Public Declare Function CloseHandle _ Lib "kernel32" _ (ByVal hObject As Long) _ As Long Public Declare Function CreateEvent _ Lib "kernel32" _ Alias "CreateEventA" _ (ByRef lpSecurityAttributes As SECURITY_ATTRIBUTES, _ ByVal bManualReset As Long, _ ByVal bInitialState As Long, _ ByVal lpName As String) _ As Long Public Declare Function CreateFile _ Lib "kernel32" _ Alias "CreateFileA" _ (ByVal lpFileName As String, _ ByVal dwDesiredAccess As Long, _ ByVal dwShareMode As Long, _ ByRef lpSecurityAttributes As SECURITY_ATTRIBUTES, _ ByVal dwCreationDisposition As Long, _ ByVal dwFlagsAndAttributes As Long, _ ByVal hTemplateFile As Long) _
Komunitas eLearning IlmuKomputer.Com Copyright © 2003-2007 IlmuKomputer.Com
155
As Long Public Declare Function FormatMessage _ Lib "kernel32" _ Alias "FormatMessageA" _ (ByVal dwFlags As Long, _ ByRef lpSource As Any, _ ByVal dwMessageId As Long, _ ByVal dwLanguageZId As Long, _ ByVal lpBuffer As String, _ ByVal nSize As Long, _ ByVal Arguments As Long) _ As Long Public Declare Function HidD_FreePreparsedData _ Lib "hid.dll" _ (ByRef PreparsedData As Long) _ As Long Public Declare Function HidD_GetAttributes _ Lib "hid.dll" _ (ByVal HidDeviceObject As Long, _ ByRef Attributes As HIDD_ATTRIBUTES) _ As Long 'Declared as a function for consistency, 'but returns nothing. (Ignore the returned value.) Public Declare Function HidD_GetHidGuid _ Lib "hid.dll" _ (ByRef HidGuid As GUID) _ As Long Public Declare Function HidD_GetPreparsedData _ Lib "hid.dll" _ (ByVal HidDeviceObject As Long, _ ByRef PreparsedData As Long) _ As Long Public Declare Function HidP_GetCaps _ Lib "hid.dll" _ (ByVal PreparsedData As Long, _ ByRef Capabilities As HIDP_CAPS) _ As Long Public Declare Function HidP_GetValueCaps _ Lib "hid.dll" _ (ByVal ReportType As Integer, _ ByRef ValueCaps As Byte, _ ByRef ValueCapsLength As Integer, _ ByVal PreparsedData As Long) _ As Long Public Declare Function lstrcpy _ Lib "kernel32" _ Alias "lstrcpyA" _ (ByVal dest As String, _ ByVal source As Long) _ As String Public Declare Function lstrlen _ Lib "kernel32" _ Alias "lstrlenA" _ (ByVal source As Long) _ As Long
Komunitas eLearning IlmuKomputer.Com Copyright © 2003-2007 IlmuKomputer.Com
156
Public Declare Function ReadFile _ Lib "kernel32" _ (ByVal hFile As Long, _ ByRef lpBuffer As Byte, _ ByVal nNumberOfBytesToRead As Long, _ ByRef lpNumberOfBytesRead As Long, _ ByRef lpOverlapped As OVERLAPPED) _ As Long Public Declare Function ResetEvent _ Lib "kernel32" _ (ByVal hEvent As Long) _ As Long Public Declare Function RtlMoveMemory _ Lib "kernel32" _ (dest As Any, _ src As Any, _ ByVal Count As Long) _ As Long Public Declare Function SetupDiCreateDeviceInfoList _ Lib "setupapi.dll" _ (ByRef ClassGuid As GUID, _ ByVal hwndParent As Long) _ As Long Public Declare Function SetupDiDestroyDeviceInfoList _ Lib "setupapi.dll" _ (ByVal DeviceInfoSet As Long) _ As Long Public Declare Function SetupDiEnumDeviceInterfaces _ Lib "setupapi.dll" _ (ByVal DeviceInfoSet As Long, _ ByVal DeviceInfoData As Long, _ ByRef InterfaceClassGuid As GUID, _ ByVal MemberIndex As Long, _ ByRef DeviceInterfaceData As SP_DEVICE_INTERFACE_DATA) _ As Long Public Declare Function SetupDiGetClassDevs _ Lib "setupapi.dll" _ Alias "SetupDiGetClassDevsA" _ (ByRef ClassGuid As GUID, _ ByVal Enumerator As String, _ ByVal hwndParent As Long, _ ByVal Flags As Long) _ As Long Public Declare Function SetupDiGetDeviceInterfaceDetail _ Lib "setupapi.dll" _ Alias "SetupDiGetDeviceInterfaceDetailA" _ (ByVal DeviceInfoSet As Long, _ ByRef DeviceInterfaceData As SP_DEVICE_INTERFACE_DATA, _ ByVal DeviceInterfaceDetailData As Long, _ ByVal DeviceInterfaceDetailDataSize As Long, _ ByRef RequiredSize As Long, _ ByVal DeviceInfoData As Long) _ As Long Public Declare Function WaitForSingleObject _ Lib "kernel32" _
Komunitas eLearning IlmuKomputer.Com Copyright © 2003-2007 IlmuKomputer.Com
157
(ByVal hHandle As Long, _ ByVal dwMilliseconds As Long) _ As Long Public Declare Function WriteFile _ Lib "kernel32" _ (ByVal hFile As Long, _ ByRef lpBuffer As Byte, _ ByVal nNumberOfBytesToWrite As Long, _ ByRef lpNumberOfBytesWritten As Long, _ ByVal lpOverlapped As Long) _ As Long
Setelah selesai membuat deklarasi module untuk API (Apidecalaration.bas), kita kembali ke Form Utama, yang terdiri dari beberapa komponen seperti terlihat pada Gambar 5.13. Tata letak form dibuat sama dengan kelas CDC Virtual COM pada bab 10. Nama dan properti semua komponen pada form1 aplikasi VB6 ditunjukkan oleh Gambar 5.13. Perbedaan dengan aplikasi emulate serial over USB adalah tidak menggunakan komponen MSComm dan menggunakan 2 timer. Sedangkan komponen pasif yang digunakan mayoritas adalah sama. Nilai properti untuk masing-masing komponen pasif juga masih sama dengan bab 10. Hal tersebut karena pengolahan data per byte yang diterima juga tidak berubah. Perubahan dasar yang dilakukan hanyalah pada sisi komunikasi.
Gambar 5.13. Rancangan Form Windows Aplikasi untuk VB 6
Masuk ke pemrograman utama, berikut ini merupakan aplikasi pengolahan data yang diterima dari PIC18F4550 dengan kelas HID. Pertama kali adalah pendeklarasian variable: Komunitas eLearning IlmuKomputer.Com Copyright © 2003-2007 IlmuKomputer.Com
158
Dim bAlertable As Long Dim Capabilities As HIDP_CAPS Dim DataString As String Dim DetailData As Long Dim DetailDataBuffer() As Byte Dim DeviceAttributes As HIDD_ATTRIBUTES Dim DevicePathName As String Dim DeviceInfoSet As Long Dim ErrorString As String Dim EventObject As Long Dim HIDHandle As Long Dim HIDOverlapped As OVERLAPPED Dim LastDevice As Boolean Dim MyDeviceDetected As Boolean Dim MyDeviceInfoData As SP_DEVINFO_DATA Dim MyDeviceInterfaceDetailData As SP_DEVICE_INTERFACE_DETAIL_DATA Dim MyDeviceInterfaceData As SP_DEVICE_INTERFACE_DATA Dim Needed As Long Dim OutputReportData(7) As Byte Dim PreparsedData As Long Dim ReadHandle As Long Dim Result As Long Dim Security As SECURITY_ATTRIBUTES Dim Timeout As Boolean Dim ByteValue1 As Byte Dim ByteValue2 As Byte Dim ByteValue3 As Byte Dim ByteValue4 As Byte Dim ByteValue5 As Byte Dim ByteValue6 As Byte Dim ByteValue7 As Byte Dim ByteValue8 As Byte Dim Bytes(64) As Byte Dim VoltageCh0, VoltageCh1, VoltageCh2, VoltageCh3 As Double Dim Delay As Double Dim DataMasuk() As Byte Dim Voltage0, Voltage1, Voltage2, Voltage3 As Single Dim Nilai_PortB, Mod_B As Integer Dim KelompokData As Byte Dim ADC0L, ADC0H, ADC1L, ADC1H, ADC2L, ADC2H, ADC3L, ADC3H As Byte Dim PortD0, PortD1, PortD2, PortD3, PortD4, PortD5, PortD6, PortD7 As Byte Dim Counter As Integer Dim i As Integer Const MyVendorID = &H900 Const MyProductID = &H100 Function FindTheHid() As Boolean Dim Count As Integer Dim GUIDString As String Dim HidGuid As GUID Dim MemberIndex As Long LastDevice = False MyDeviceDetected = False Security.lpSecurityDescriptor = 0 Security.bInheritHandle = True Security.nLength = Len(Security)
Bebeberapa fungsi API yang berfungsi mengatur GUID dideklarasikan sebagai berikut: Komunitas eLearning IlmuKomputer.Com Copyright © 2003-2007 IlmuKomputer.Com
159
'**************************************************************************** 'HidD_GetHidGuid 'Get the GUID for all system HIDs. 'Returns: the GUID in HidGuid. 'The routine doesn't return a value in Result 'but the routine is declared as a function for consistency with the other API calls. '**************************************************************************** Result = HidD_GetHidGuid(HidGuid) Call DisplayResultOfAPICall("GetHidGuid") GUIDString = _ Hex$(HidGuid.Data1) & "-" & _ Hex$(HidGuid.Data2) & "-" & _ Hex$(HidGuid.Data3) & "-" For Count = 0 To 7 'Ensure that each of the 8 bytes in the GUID displays two characters. If HidGuid.Data4(Count) >= &H10 Then GUIDString = GUIDString & Hex$(HidGuid.Data4(Count)) & " " Else GUIDString = GUIDString & "0" & Hex$(HidGuid.Data4(Count)) & " " End If Next Count '*************************************************************************** 'SetupDiGetClassDevs 'Returns: a handle to a device information set for all installed devices. 'Requires: the HidGuid returned in GetHidGuid. '**************************************************************************** DeviceInfoSet = SetupDiGetClassDevs _ (HidGuid, _ vbNullString, _ 0, _ (DIGCF_PRESENT Or DIGCF_DEVICEINTERFACE)) Call DisplayResultOfAPICall("SetupDiClassDevs") DataString = GetDataString(DeviceInfoSet, 32) '**************************************************************************** 'SetupDiEnumDeviceInterfaces 'On return, MyDeviceInterfaceData contains the handle to a 'SP_DEVICE_INTERFACE_DATA structure for a detected device. 'Requires: 'the DeviceInfoSet returned in SetupDiGetClassDevs. 'the HidGuid returned in GetHidGuid. 'An index to specify a device. '**************************************************************************** 'Begin with 0 and increment until no more devices are detected. MemberIndex = 0 Do MyDeviceInterfaceData.cbSize = LenB(MyDeviceInterfaceData) Result = SetupDiEnumDeviceInterfaces _ (DeviceInfoSet, _ 0, _ HidGuid, _ MemberIndex, _ MyDeviceInterfaceData) Call DisplayResultOfAPICall("SetupDiEnumDeviceInterfaces") If Result = 0 Then LastDevice = True
Komunitas eLearning IlmuKomputer.Com Copyright © 2003-2007 IlmuKomputer.Com
160
'If a device exists, display the information returned. If Result <> 0 Then MyDeviceInfoData.cbSize = Len(MyDeviceInfoData) Result = SetupDiGetDeviceInterfaceDetail _ (DeviceInfoSet, _ MyDeviceInterfaceData, _ 0, _ 0, _ Needed, _ 0) DetailData = Needed Call DisplayResultOfAPICall("SetupDiGetDeviceInterfaceDetail") 'Store the structure's size. MyDeviceInterfaceDetailData.cbSize = _ Len(MyDeviceInterfaceDetailData) 'Use a byte array to allocate memory for 'the MyDeviceInterfaceDetailData structure ReDim DetailDataBuffer(Needed) Call RtlMoveMemory _ (DetailDataBuffer(0), _ MyDeviceInterfaceDetailData, _ 4) Result = SetupDiGetDeviceInterfaceDetail _ (DeviceInfoSet, _ MyDeviceInterfaceData, _ VarPtr(DetailDataBuffer(0)), _ DetailData, _ Needed, _ 0) Call DisplayResultOfAPICall(" Result of second call: ") 'Convert the byte array to a string. DevicePathName = CStr(DetailDataBuffer()) 'Convert to Unicode. DevicePathName = StrConv(DevicePathName, vbUnicode) 'Strip cbSize (4 bytes) from the beginning. DevicePathName = Right$(DevicePathName, Len(DevicePathName) - 4) HIDHandle = CreateFile _ (DevicePathName, _ GENERIC_READ Or GENERIC_WRITE, _ (FILE_SHARE_READ Or FILE_SHARE_WRITE), _ Security, _ OPEN_EXISTING, _ 0&, _ 0) Call DisplayResultOfAPICall("CreateFile") DeviceAttributes.Size = LenB(DeviceAttributes) Result = HidD_GetAttributes _ (HIDHandle, _ DeviceAttributes) Call DisplayResultOfAPICall("HidD_GetAttributes") If (DeviceAttributes.VendorID = MyVendorID) And _ (DeviceAttributes.ProductID = MyProductID) Then MyDeviceDetected = True
Komunitas eLearning IlmuKomputer.Com Copyright © 2003-2007 IlmuKomputer.Com
161
Else MyDeviceDetected = False Result = CloseHandle _ (HIDHandle) DisplayResultOfAPICall ("CloseHandle") End If End If 'Keep looking until we find the device or there are no more left to examine. MemberIndex = MemberIndex + 1 Loop Until (LastDevice = True) Or (MyDeviceDetected = True) 'Free the memory reserved for the DeviceInfoSet returned by ‘SetupDiGetClassDevs. Result = SetupDiDestroyDeviceInfoList _ (DeviceInfoSet) Call DisplayResultOfAPICall("DestroyDeviceInfoList") If MyDeviceDetected = True Then FindTheHid = True Status_lbl.Caption = "Terhubung dengan PIC" 'Learn the capabilities of the device Call GetDeviceCapabilities ReadHandle = CreateFile _ (DevicePathName, _ (GENERIC_READ Or GENERIC_WRITE), _ (FILE_SHARE_READ Or FILE_SHARE_WRITE), _ Security, _ OPEN_EXISTING, _ FILE_FLAG_OVERLAPPED, _ 0) Call DisplayResultOfAPICall("CreateFile, ReadHandle") Call PrepareForOverlappedTransfer Else Status_lbl.Caption = "Tidak terhubung dengan PIC" End If End Function 'End fuction of Function FindTheHID() Private Function GetDataString _ (Address As Long, _ Bytes As Long) _ As String 'Retrieves a string of length Bytes from memory, beginning at Address. 'Adapted from Dan Appleman's "Win32 API Puzzle Book" Dim Offset As Integer Dim Result$ Dim ThisByte As Byte For Offset = 0 To Bytes - 1 Call RtlMoveMemory(ByVal VarPtr(ThisByte), ByVal Address + Offset, 1) If (ThisByte And &HF0) = 0 Then Result$ = Result$ & "0" End If Result$ = Result$ & Hex$(ThisByte) & " " Next Offset GetDataString = Result$ End Function Private Function GetErrorString _ (ByVal LastError As Long) _ As String 'Returns the error message for the last error. 'Adapted from Dan Appleman's "Win32 API Puzzle Book" Dim Bytes As Long Dim ErrorString As String ErrorString = String$(129, 0) Bytes = FormatMessage _ (FORMAT_MESSAGE_FROM_SYSTEM, _
Komunitas eLearning IlmuKomputer.Com Copyright © 2003-2007 IlmuKomputer.Com
162
0&, _ LastError, _ 0, _ ErrorString$, _ 128, _ 0) 'Subtract two characters from the message to strip the CR and LF. If Bytes > 2 Then GetErrorString = Left$(ErrorString, Bytes - 2) End If End Function Private Sub DisplayResultOfAPICall(FunctionName As String) 'Display the results of an API call. Dim ErrorString As String ErrorString = GetErrorString(Err.LastDllError) 'Scroll to the bottom of the list box. 'lstResults.ListIndex = lstResults.ListCount - 1 End Sub
D0_cxb , D1_cbx,… sampai D8_cbx merupakan komponen checkBox yang berfungsi untuk mengatur keluaran bit para Port D. Jika Port D0 dicheck oleh pengguna, maka Port D bit 0 akan menyala. Begitu pula sebaliknya, jika Port D ke-n tidak dicheck, maka PortD bit – n akan mati. Nilai “80” merupakan nilai desimal dari ASCII “P” dan 112 adalah nilai desimal dari “p”. Nilai “81” sama dengan “Q” dalam ASCII, dan seterusnya. Berikut ini merupakan script untuk D0_cxb sampai D7_cxb. Private Sub D0_cxb_Click() If D0_cxb.Value = 1 Then PortD0 = 80 Else PortD0 = 112 End If End Sub Private Sub D1_cxb_Click() If D1_cxb.Value = 1 Then PortD1 = 81 Else PortD1 = 113 End If End Sub Private Sub D2_cxb_Click() If D2_cxb.Value = 1 Then PortD2 = 82 Else PortD2 = 114 End If End Sub Private Sub D3_cxb_Click() If D3_cxb.Value = 1 Then PortD3 = 83 Else PortD3 = 115 End If End Sub Private Sub D4_cxb_Click() If D4_cxb.Value = 1 Then
Komunitas eLearning IlmuKomputer.Com Copyright © 2003-2007 IlmuKomputer.Com
163
PortD4 = 84 Else PortD4 = 116 End If End Sub Private Sub D5_cxb_Click() If D5_cxb.Value = 1 Then PortD5 = 85 Else PortD5 = 117 End If End Sub Private Sub D6_cxb_Click() If D6_cxb.Value = 1 Then PortD6 = 86 Else PortD6 = 118 End If End Sub Private Sub D7_cxb_Click() If D7_cxb.Value = 1 Then PortD7 = 87 Else PortD7 = 119 End If End Sub
Pada waktu pertama kali program aplikasi berjalan, beberapa pengaturan komponen seperti pada port D dan timer untuk komunikasi ditangani oleh Subrutin Form_Load. Berikut merupakan listing kode untuk Form1 pertama kali di load : Private Sub Form_Load() Form1.Show Status_lbl.Caption = "Tidak terhubung dengan PIC" DelayTmr.Enabled = False BacaDataTmr.Interval = 1 BacaDataTmr.Enabled = True PortD0 = 112 PortD1 = 113 PortD2 = 114 PortD3 = 115 PortD4 = 116 PortD5 = 117 PortD6 = 118 PortD7 = 119 End Sub
Fungsi Unload berfungsi untuk memutus hubungan dengan device. Fungsi ini nantinya dipanggil jika user menutup aplikasi. Private Sub Form_Unload(Cancel As Integer) Call Shutdown End Sub Private Sub GetDeviceCapabilities() '**************************************************************************** 'HidD_GetPreparsedData 'Returns: a pointer to a buffer containing information about the device's capabilities. 'Requires: A handle returned by CreateFile.
Komunitas eLearning IlmuKomputer.Com Copyright © 2003-2007 IlmuKomputer.Com
164
'There's no need to access the buffer directly, 'but HidP_GetCaps and other API functions require a pointer to the buffer. '**************************************************************************** Dim ppData(29) As Byte Dim ppDataString As Variant 'Preparsed Data is a pointer to a routine-allocated buffer. Result = HidD_GetPreparsedData _ (HIDHandle, _ PreparsedData) Call DisplayResultOfAPICall("HidD_GetPreparsedData") 'Copy the data at PreparsedData into a byte array. Result = RtlMoveMemory _ (ppData(0), _ PreparsedData, _ 30) Call DisplayResultOfAPICall("RtlMoveMemory") ppDataString = ppData() 'Convert the data to Unicode. ppDataString = StrConv(ppDataString, vbUnicode) '************************************************************************ 'HidP_GetCaps 'Find out the device's capabilities. 'For standard devices such as joysticks, you can find out the specific 'capabilities of the device. 'For a custom device, the software will probably know what the device is ‘capable of, 'so this call only verifies the information. 'Requires: The pointer to a buffer containing the information. 'The pointer is returned by HidD_GetPreparsedData. 'Returns: a Capabilites structure containing the information. '****************************************************************************** Result = HidP_GetCaps _ (PreparsedData, _ Capabilities) Call DisplayResultOfAPICall("HidP_GetCaps") '**************************************************************************** 'HidP_GetValueCaps 'Returns a buffer containing an array of HidP_ValueCaps structures. 'Each structure defines the capabilities of one value. 'This application doesn't use this data. '**************************************************************************** Dim ValueCaps(1023) As Byte Result = HidP_GetValueCaps _ (HidP_Input, _ ValueCaps(0), _ Capabilities.NumberInputValueCaps, _ PreparsedData) Call DisplayResultOfAPICall("HidP_GetValueCaps") 'lstResults.AddItem "ValueCaps= " & GetDataString((VarPtr(ValueCaps(0))), ‘180) 'To use this data, copy the byte array into an array of structures. 'Free the buffer reserved by HidD_GetPreparsedData Result = HidD_FreePreparsedData _ (PreparsedData)
Komunitas eLearning IlmuKomputer.Com Copyright © 2003-2007 IlmuKomputer.Com
165
Call DisplayResultOfAPICall("HidD_FreePreparsedData") End Sub Private Sub PrepareForOverlappedTransfer() '**************************************************************************** 'CreateEvent 'Creates an event object for the overlapped structure used with ReadFile. 'Requires a security attributes structure or null, 'Manual Reset = True (ResetEvent resets the manual reset object to nonsignaled), 'Initial state = True (signaled), 'and event object name (optional) 'Returns a handle to the event object. '*************************************************************************** If EventObject = 0 Then EventObject = CreateEvent _ (Security, _ True, _ True, _ "") End If Call DisplayResultOfAPICall("CreateEvent") 'Set the members of the overlapped structure. HIDOverlapped.Offset = 0 HIDOverlapped.OffsetHigh = 0 HIDOverlapped.hEvent = EventObject End Sub
Fungsi untuk menulis report ke device (endpoint) adalah sebagai berikut: (1 byte) Private Sub WriteReport() 'Send data to the device. Dim Count As Integer Dim NumberOfBytesRead As Long Dim NumberOfBytesToSend As Long Dim NumberOfBytesWritten As Long Dim ReadBuffer() As Byte Dim SendBuffer() As Byte 'The SendBuffer array begins at 0, so subtract 1 from the number of bytes. ReDim SendBuffer(Capabilities.OutputReportByteLength - 1) '**************************************************************************** 'WriteFile 'Sends a report to the device. 'Returns: success or failure. 'Requires: the handle returned by CreateFile and 'The output report byte length returned by HidP_GetCaps '**************************************************************************** 'The first byte is the Report ID SendBuffer(0) = 0 'The next bytes are data For Count = 1 To Capabilities.OutputReportByteLength - 1 SendBuffer(Count) = OutputReportData(Count - 1) Next Count NumberOfBytesWritten = 0 Result = WriteFile _ (HIDHandle, _ SendBuffer(0), _ CLng(Capabilities.OutputReportByteLength), _ NumberOfBytesWritten, _ 0) Call DisplayResultOfAPICall("WriteFile") End Sub
Komunitas eLearning IlmuKomputer.Com Copyright © 2003-2007 IlmuKomputer.Com
166
Private Sub Shutdown() 'Actions that must execute when the program ends. 'Close the open handles to the device. BacaDataTmr.Enabled = False Result = CloseHandle _ (HIDHandle) Call DisplayResultOfAPICall("CloseHandle (HIDHandle)") Result = CloseHandle _ (ReadHandle) Call DisplayResultOfAPICall("CloseHandle (ReadHandle)") End Sub
Fungsi untuk membaca report dari device (endpoint) adalah sebagai berikut: (8 byte) Private Sub ReadReport() 'Read data from the device. Dim Count Dim NumberOfBytesRead As Long 'Allocate a buffer for the report. 'Byte 0 is the report ID. Dim ReadBuffer() As Byte Dim UBoundReadBuffer As Integer '**************************************************************************** 'ReadFile 'Returns: the report in ReadBuffer. 'Requires: a device handle returned by CreateFile '(for overlapped I/O, CreateFile must be called with FILE_FLAG_OVERLAPPED), 'the Input report length in bytes returned by HidP_GetCaps, 'and an overlapped structure whose hEvent member is set to an event object. '*************************************************************************** ’The ReadBuffer array begins at 0, so subtract 1 from the number of bytes. ReDim ReadBuffer(Capabilities.InputReportByteLength - 1) Result = ReadFile _ (ReadHandle, _ ReadBuffer(0), _ CLng(Capabilities.InputReportByteLength), _ NumberOfBytesRead, _ HIDOverlapped) Call DisplayResultOfAPICall("ReadFile") bAlertable = True '****************************************************************************** 'WaitForSingleObject 'Used with overlapped ReadFile. 'Returns when ReadFile has received the requested amount of data or on timeout. 'Requires an event object created with CreateEvent 'and a timeout value in milliseconds. '****************************************************************************** Result = WaitForSingleObject _ (EventObject, _ 6000) Call DisplayResultOfAPICall("WaitForSingleObject") 'Find out if ReadFile completed or timeout. Select Case Result Case WAIT_TIMEOUT 'Timeout 'Cancel the operation '************************************************************* 'CancelIo 'Cancels the ReadFile 'Requires the device handle. 'Returns non-zero on success. '************************************************************* Result = CancelIo _
Komunitas eLearning IlmuKomputer.Com Copyright © 2003-2007 IlmuKomputer.Com
167
(ReadHandle) Call DisplayResultOfAPICall("CancelIo") CloseHandle (HIDHandle) Call DisplayResultOfAPICall("CloseHandle (HIDHandle)") CloseHandle (ReadHandle) Call DisplayResultOfAPICall("CloseHandle (ReadHandle)") MyDeviceDetected = False Case Else MyDeviceDetected = False End Select For Count = 1 To UBound(ReadBuffer) ByteValue1 = (ReadBuffer(1)) ByteValue2 = (ReadBuffer(2)) ByteValue3 = (ReadBuffer(3)) ByteValue4 = (ReadBuffer(4)) ByteValue5 = (ReadBuffer(5)) ByteValue6 = (ReadBuffer(6)) ByteValue7 = (ReadBuffer(7)) ByteValue8 = (ReadBuffer(8)) Next Count '**************************************************************************** 'ResetEvent 'Sets the event object in the overlapped structure to non-signaled. 'Requires a handle to the event object. 'Returns non-zero on success. '**************************************************************************** Call ResetEvent(EventObject) Call DisplayResultOfAPICall("ResetEvent") End Sub 'End of Sub ReadReport()
Pembacan dan penulisan report pada aplikasi dengan PIC18F4550 merupakan sebuah proses real time. Komponen yang berkaitan dengan proses ini adalah sebuah timer BacaDataTmr. Nilai interval timer ini adalah 1 dan dideklarasikan pada waktu pertama kali form diload. Kode untuk komponen ini berupa penulisan “1H” dan “2H” (kode bilangan, bukan ASCII). Selain itu, 8 byte report in yang diterima, harus disimpan dalam variable (dalam hal ini ByteValue1 sampai BytevValue8) untuk selanjutnya dikalkulasi. Private Sub BacaDataTmr_Timer() Dim Count As Integer If MyDeviceDetected = False Then MyDeviceDetected = FindTheHid End If If MyDeviceDetected = True Then OutputReportData(0) = 1 Call WriteReport Call ReadReport 'Read a report from the device. ADC0L = ByteValue1 ADC0H = ByteValue2 ADC1L = ByteValue3 ADC1H = ByteValue4 ADC2L = ByteValue5 ADC2H = ByteValue6 ADC3L = ByteValue7 ADC3H = ByteValue8 OutputReportData(0) = 2 Call WriteReport Call ReadReport Nilai_PortB = ByteValue1 OutputReportData(0) = PortD0 Call WriteReport OutputReportData(0) = PortD1 Call WriteReport OutputReportData(0) = PortD2
Komunitas eLearning IlmuKomputer.Com Copyright © 2003-2007 IlmuKomputer.Com
168
Call WriteReport OutputReportData(0) = PortD3 Call WriteReport OutputReportData(0) = PortD4 Call WriteReport OutputReportData(0) = PortD5 Call WriteReport OutputReportData(0) = PortD6 Call WriteReport OutputReportData(0) = PortD7 Call WriteReport End If Voltage0 = (((ADC0H And 3) * 256) + ADC0L) / 204.6 ADC0_txt.Text = Format$(Voltage0, "#.00") ADC0.Value = Voltage0 * 4096 / 5 Voltage1 = (((ADC1H And 3) * 256) + ADC1L) / 204.6 ADC1_txt.Text = Format$(Voltage1, "#.00") ADC1.Value = Voltage1 * 4096 / 5 Voltage2 = (((ADC2H And 3) * 256) + ADC2L) / 204.6 ADC2_txt.Text = Format$(Voltage2, "#.00") ADC2.Value = Voltage2 * 4096 / 5 Voltage3 = (((ADC3H And 3) * 256) + ADC3L) / 204.6 ADC3_txt.Text = Format$(Voltage3, "#.00") ADC3.Value = Voltage3 * 4096 / 5 Mod_B = Nilai_PortB Mod 2 B0_txt.Text = Mod_B If Mod_B = 1 Then Nilai_PortB = (Nilai_PortB / 2) - 0.5 Else Nilai_PortB = Nilai_PortB / 2 End If Mod_B = Nilai_PortB Mod 2 B1_txt.Text = Mod_B If Mod_B = 1 Then Nilai_PortB = (Nilai_PortB / 2) - 0.5 Else Nilai_PortB = Nilai_PortB / 2 End If Mod_B = Nilai_PortB Mod 2 B2_txt.Text = Mod_B If Mod_B = 1 Then Nilai_PortB = (Nilai_PortB / 2) - 0.5 Else Nilai_PortB = Nilai_PortB / 2 End If Mod_B = Nilai_PortB Mod 2 B3_txt.Text = Mod_B If Mod_B = 1 Then Nilai_PortB = (Nilai_PortB / 2) - 0.5 Else Nilai_PortB = Nilai_PortB / 2 End If Mod_B = Nilai_PortB Mod 2 B4_txt.Text = Mod_B If Mod_B = 1 Then Nilai_PortB = (Nilai_PortB / 2) - 0.5 Else Nilai_PortB = Nilai_PortB / 2 End If
Komunitas eLearning IlmuKomputer.Com Copyright © 2003-2007 IlmuKomputer.Com
169
Mod_B = Nilai_PortB Mod 2 B5_txt.Text = Mod_B If Mod_B = 1 Then Nilai_PortB = (Nilai_PortB / 2) - 0.5 Else Nilai_PortB = Nilai_PortB / 2 End If Mod_B = Nilai_PortB Mod 2 B6_txt.Text = Mod_B If Mod_B = 1 Then Nilai_PortB = (Nilai_PortB / 2) - 0.5 Else Nilai_PortB = Nilai_PortB / 2 End If B7_txt.Text = Nilai_PortB End Sub
Selain timer untuk pengolahan data, ada timer satu lagi yang berfungsi untuk membangkitkan delay pada waktu pertama kali form diload. Nama properti untuk timer tersebut adalah Delay_Tmrdengan script kode sebagai berikut : Private Sub DelayTmr_Timer() Timeout = True DelayTmr.Enabled = False End Sub
Apabila semua kode diatas ditulis dalam sebuah program aplikasi Visual Basic 6, maka aplikasi Host siap untuk bertatap muka dengan device dalam hal ini PIC18F4550.
Hasil Akhir Aplikasi Pertama kali device dicolokkan ke port hub, Windows akan mendeteksi adanya device baru. Deteksi ini dilakukan pertama kali dengan mendeteki ProdukID dan VendorID dari device. Oleh karena itu Produk dan Vendor ID antara masing-masing device tidak boleh sama, walaupun mempunyai jenis dan kelas yang berbeda. Aplikasi di sisi host pada waktu berjalan juga mendeteksi keberadaan device, namun untuk bertukar data (report). Dan proses ini berjalan di atas lingkungan Windows. Oleh sebeb itu, Windows harus pertama kali mendeteksi adanya device. Baru setelah itu aplikasi bisa bertukar data (report). Pada Gambar 5.14 terlihat hasil aplikasi yang telah kita buat berjalan pada platform Windows XP. Jika karena suatu hal menyebabkan komputer dengan PIC tidak bisa saling bertukar report, maka aplikasi tetap akan berjalan, karena memang dasar komunikasi yang terjadi atas dasar interrupt. Aplikasi HID yang berbasiskan Visual Basic dapat berjalan dengan baik, karena tidak membutuhkan komponen yang perlu didaftarkan di seri Windows Vista atau Windows 7. Oleh karena itu, hasil aplikasi juga bisa langsung digunakan pada lingkungan Windows 7. Hasil aplikasi akhir HID_ku, host dapat menampilkan nilai ADC pada kanal 0, ADC channel 1 dan seterusnya. Ketika user mengklik pada PortD0, atau PortD1 maka port D yang ada di mikrokontroler juga akan mempunyai logik sesuai dengan pilihan user. Semuanya dilakukan dalam satu siklus waktu sehingga user akan mengenali aplikasi yang berjalan sebagai aplikasi real time.
Komunitas eLearning IlmuKomputer.Com Copyright © 2003-2007 IlmuKomputer.Com
170
Gambar 5.14. Hasil akhir aplikasi Win XP. Terlihat device langsung di deteksi oleh aplikasi
Gambar 5.15. Jika device di cabut dari sistem, maka aplikasi akan secara langsung mendeteksi “ketidak beradaan” device.
Apabila ada masalah koneksi yang menyebabkan tidak terhubungnya device dengan host maka dalam aplikasi, label keterangan koneksi akan menyatakan “Tidak terhubung dengan device” (Gambar 5.15). Begitu device terhubung kembali, maka aplikasii host akan berjalan lagi seperti sedia kala (Gambar 5.14). Pada Windows 7 proses deteksi device juga menuntut pengguna untuk merestart sistem sebelum nomor Produk dan Vendor ID terekam dalam regristry Windows. Ketika pertama kali device dihubungkan dengan Windows 7 dalam Device Manager akan terdeteksi sebuah kelas HID Input Device (Gambar 5.16).
Komunitas eLearning IlmuKomputer.Com Copyright © 2003-2007 IlmuKomputer.Com
171
Gambar 5.16. Device Manager pada Windows 7
Klik kanan pada jenis device yang terdeteksi, maka dapat dilihat nilai properti mulai dari Product ID, sampai descriptor string yang digunakan oleh device.(Gambar 5.17)
Gambar 5.17. Properti device pada Windows 7
Seperti telah disinggung sebelumnya kita tidak bisa menggunakan nilai Product dan Vendor ID secara sembarangan. Jika penggunaan device yang kita buat untuk khalayak, nilai Product ID dan Vendor ID sama dengan device milik pengembang yang lain, maka akan menimbulkan konflik. Nilai Product dan Vendor ID diatur dan didaftarkan di USBIF (www.usb.org), dan tentu saja sebagai pengembang device ada harga yang harus dibayar agar kita mempunyai hak menggunakan nomor Product ID dan Vendor ID tertentu.
Gambar 5.18. Aplikasi berjalan normal pada Windows 7 (sebelum terhubung dengan device) Komunitas eLearning IlmuKomputer.Com Copyright © 2003-2007 IlmuKomputer.Com
172
Gambar 5.19. Aplikasi berjalan pada Wondows 7 (setelah terhubung dengan device)
Setelah semua proses identifikasi kelas HID pada Windows 7 terlampaui, aplikasi Visual Basic yang sudah kita buat juga mampu berjalan dilingkungan Windows 7 tanpa ada masalah yang berarti (Gambar 5.19). Pada kasus penggunaan kelas HID pengguna disuguhkan pada sebuah aplikasi yang ”anti crash” walaupun device di lepas kemudian dicolokkan kembali ke hub. Para pengembang device (embedded programmer) bisa memilih salah satu diantara beberapa kelas yang dianggap relevan untuk device yang dibuat. Kelas HID jelas tidak memungkinkan untuk keperluan data logger yang menuntut kepresisian waktu di bawah 10 mili detik, sedangkan emulating serial over USB bisa jadi pilihan yang bagus, namun kelancaran data dan pengolahannya perlu ditingkatkan. Platform .NET yang diusung dalam Microsoft Visual Studio veri 8 ke atas menyediakan sebuah solusi yang lebih baik ketimbang kita masih berkutat dengan VB6, sementara regristrasi komponen pendukung (MSCOmm) patut dipertanyakan pada versi Windows yang semakin baru. Kelas virtual COM juga memungkinkan programmer host menggunakan bahasa selain VB misalnya Java. Tentu saja lebih banyak keunggulan dengan bahasa ini karena dukungan yang multi platform. Namun penggunaan Java untuk kelas HID juga menuai beberapa kesulitan mengingat pemrograman untuk USB mau tidak mau berhubungan dengan hardware dan sistem kernel sebuah sistem operasi. Transfer Bulk barangkali menjadi solusi yang paling tepat bagi device yang membutuhkan transfer cepat dan besar. Kelas yang diusung transfer jenis ini otomastis akan menggunakan kelas khusus (custom class). Penggunaan kelas ini banyak digunakan jenis data logger, mixer audio, atau transfer data pada mass strorage tertentu (misalnya SDCard pada ponsel. USB versi 3 menawarkan sebuah solusi yang sangat bagus mengingat kecepatannya. Namun demikian, keunggulan yang tawarkan juga diimbangi dengan desain harware, programming, serta protokol yang lebih kompek.
Komunitas eLearning IlmuKomputer.Com Copyright © 2003-2007 IlmuKomputer.Com
173
REFERENSI 1. Axleson, Jan. 2009. USB Complete: Everything you need to Develop USB peripherals. Madison: Lakeview Research LLC. 2. Sutadi, Dwi 2004. I/O BUS & MotherBoard. Yogyakarta: Andi Offset. 3. Brown, Eric. 2006. USB INSTRUMENTATION, Yale University. 4. USB Implemented Forum, http://www.usb.org. 5. HID Page, Lake View Research, http://www.lvr.com. 6. PIC 14F4550 Datasheet, USB PIC18F4550 Seminar Publication. http://www.microchip.com. 7. Olimex Ltd. 2007.PIC-USB USB-4550 development. http://www.olimex.com. 8. Wiki about Microchip USB PIC. http://pic18fusb.online.fr. 9. Embed Inc PIC 18F USB Framework http://www.embedinc.com. 10. USB Interface Microchip PIC18F4550. http://www.sixca.com. 11. USB I/O on the PIC18F4550. http://3dreplicators.com. 12. PIC18 USB Support. http://www.oshonsoft.com. 13. PICPgm Free PIC Development Programmer for Windows : http://members.aon.at/electronics/pic/picpgm/_main.html 14. Evan. 2006. Understanding the Microchip USB Firmware. http://eegeek.net 15. WinPic800 documentation, software. http://www.winpic800.com. 16. Fast PICUSB CDC. http://ostry.w.szu.pl. 17. Migrate Your Serial Application To USB The Easy Way. http://electronicdesign.com. 18. USB in a nutshell. http://www.beyondlogic.com.
Komunitas eLearning IlmuKomputer.Com Copyright © 2003-2007 IlmuKomputer.Com
174
Biografi Penulis Aman Subanjar. Menyelesaikan pendidikan di UNY dan ITB. Pernah bekerja sebagai embeded system designer di industri selama beberapa tahun sebelum akhirnya bekerja di salah satu instansi pemerintah. Sertifikasi yang pernah diperoleh diantaranya CHFI dan CDCP. Tulisan lain dapat dilihat di jurnal Kemkominfo.
Komunitas eLearning IlmuKomputer.Com Copyright © 2003-2007 IlmuKomputer.Com
175