- USB ड्राइवर डेवलपमेंट को अक्सर kernel-level काम माना जाता है, लेकिन वास्तव में इसे socket programming जैसी कठिनाई के साथ user space में भी लागू किया जा सकता है
- libusb का उपयोग करके kernel code लिखे बिना device enumeration, control transfer, और data send/receive सब किया जा सकता है
- USB communication Control, Bulk, Interrupt, Isochronous इन चार transfer types और IN/OUT directions से मिलकर बना होता है, और हर endpoint एक one-way channel की तरह काम करता है
- Android डिवाइस के Fastboot protocol को उदाहरण के रूप में लेकर, Bulk endpoint के जरिए command और response का आदान-प्रदान code से दिखाया गया है
- user space में भी पूरा USB ड्राइवर लागू किया जा सकता है, और सभी USB protocols एक जैसी बुनियादी संरचना साझा करते हैं
परिचय
- USB डिवाइस के लिए ड्राइवर लिखना अक्सर इसलिए कठिन लगता है क्योंकि यह माना जाता है कि इसके लिए kernel code संभालना पड़ता है, लेकिन वास्तव में इसकी जटिलता socket इस्तेमाल करने वाले application-level code जैसी है
- जिन डेवलपर्स के पास hardware का ज़्यादा अनुभव नहीं है, वे भी user space में USB को handle करने का तरीका सीख सकते हैं
- USB के detailed internals पर सामग्री उपलब्ध है, लेकिन शुरुआती लोगों के लिए उस तक पहुँचना कठिन हो सकता है
- USB इस्तेमाल करने के लिए embedded systems स्तर की जानकारी ज़रूरी नहीं है, इसे network socket की तरह समझकर अपनाया जा सकता है
USB डिवाइस
- उदाहरण के लिए bootloader mode में Android smartphone का उपयोग किया गया है
- यह आसानी से उपलब्ध है, protocol सरल है, और OS में default driver न होने की वजह से प्रयोग के लिए उपयुक्त है
- bootloader mode में प्रवेश हर डिवाइस में अलग हो सकता है, लेकिन आम तौर पर power button और volume button के combination से किया जा सकता है
डिवाइस की मैन्युअल enumeration
- Enumeration वह प्रक्रिया है जिसमें host डिवाइस की जानकारी माँगकर उसकी पहचान करता है, और यह डिवाइस connect होने पर अपने आप होती है
- standard devices में USB class के आधार पर driver अपने आप load हो जाता है, जबकि vendor-specific devices के लिए
VID (Vendor ID) और PID (Product ID) का उपयोग होता है
- Linux में
lsusb command से डिवाइस की जानकारी देखी जा सकती है
- उदाहरण:
ID 18d1:4ee0 Google Inc. Nexus/Pixel Device (fastboot)
18d1 Google का VID है, और 4ee0 Nexus/Pixel bootloader का PID है
lsusb -t command से class और driver status देखा जा सकता है
Class=Vendor Specific Class, Driver=[none] दिखने का मतलब है कि OS ने कोई driver load नहीं किया है
- Windows में यही जानकारी Device Manager या USB Device Tree Viewer से देखी जा सकती है
libusb से डिवाइस enumeration
- libusb library का उपयोग करके kernel code लिखे बिना user space में USB डिवाइस से communication किया जा सकता है
libusb_hotplug_register_callback() से इस तरह सेट किया जा सकता है कि किसी खास VID:PID combination वाला डिवाइस connect होने पर callback चले
- प्रोग्राम चलने के बाद डिवाइस connect करते ही
"Device plugged in!" message प्रिंट होता है
- Linux में यह डिफ़ॉल्ट रूप से काम करता है, और ज़रूरत पड़ने पर
libusb_detach_kernel_driver() से kernel driver को अलग किया जा सकता है
- Windows में
Winusb.sys driver की ज़रूरत होती है, और अगर वह न हो तो Zadig tool से उसे manually replace किया जा सकता है
डिवाइस से communication
- USB डिवाइस के साथ पहला communication Control endpoint (address 0x00) के ज़रिए होता है
libusb_control_transfer() से standard request (GET_STATUS) भेजकर डिवाइस की स्थिति पढ़ी जा सकती है
- उदाहरण response:
01 00 → पहला byte Self-Powered को दिखाता है, दूसरा Remote Wakeup unsupported को
- इसके बाद GET_DESCRIPTOR request से device descriptor लाया जा सकता है
- लौटे हुए data में
idVendor, idProduct, bDeviceClass जैसी डिवाइस जानकारी शामिल होती है
lsusb -v command से सभी descriptors (device, configuration, interface, endpoint आदि) विस्तार से देखे जा सकते हैं
- उदाहरण:
Android Fastboot interface में Bulk IN(0x81) और Bulk OUT(0x02) endpoints मौजूद हैं
एंडपॉइंट
- endpoint network port जैसी अवधारणा है, जिसके ज़रिए डिवाइस data send/receive करता है
- हर endpoint का type और direction descriptor में परिभाषित होता है
-
Control transfer type
- हर डिवाइस में एक होता है और उसका address हमेशा
0x00 होता है
- शुरुआती setup और डिवाइस जानकारी माँगने के लिए उपयोग होता है
- यह interface का हिस्सा नहीं होता, बल्कि खुद डिवाइस का हिस्सा होता है
-
Bulk transfer type
- बड़ी मात्रा में non-real-time data transfer के लिए उपयोग होता है
- उदाहरण: Mass Storage, CDC-ACM (serial), RNDIS (Ethernet)
- bandwidth अधिक होती है, लेकिन priority कम होती है
-
Interrupt transfer type
- कम मात्रा में low-latency data transfer के लिए उपयोग होता है
- keyboard, mouse जैसे डिवाइस में button input को तेज़ी से poll करने के लिए उपयोग होता है
- यह असली hardware interrupt नहीं होता, host इसे periodic request के रूप में करता है
-
Isochronous transfer type
- time-sensitive high-volume data (audio, video streaming) के लिए उपयोग होता है
- अगर delay हो जाए तो quality पर तुरंत असर दिखता है
- libusb में इसे asynchronous तरीके से handle किया जाता है
-
IN / OUT direction
- USB host-centric architecture पर आधारित है, इसलिए डिवाइस request मिलने से पहले data नहीं भेजता
IN: वह दिशा जिसमें host data प्राप्त करता है
OUT: वह दिशा जिसमें host data भेजता है
- अगर endpoint address का सबसे ऊपरी bit (MSB)
1 है, तो वह IN है; 0 है, तो OUT
- अधिकतम 127 user-defined endpoints उपयोग किए जा सकते हैं (
0x00 सिर्फ Control के लिए आरक्षित है)
- endpoint one-way होते हैं, और Fastboot interface की तरह IN/OUT pairs में बने होते हैं
Fastboot protocol
- Fastboot Android bootloader communication protocol है, जिसमें command string भेजी जाती है और बदले में 4-byte status code तथा data मिलता है
- उदाहरण:
Host: "getvar:version" → Client: "OKAY0.4"
Host: "getvar:nonexistant" → Client: "OKAY"
- libusb का उपयोग करके Fastboot command भेजने का code example
समापन
- kernel code लिखे बिना user space में पूरा USB ड्राइवर लागू करना संभव है
- सभी USB drivers एक ही बुनियादी सिद्धांत का पालन करते हैं, अंतर सिर्फ protocol का होता है
- जटिल protocols (MTP आदि) की भी बुनियादी संरचना यही रहती है, इसलिए इन्हें socket communication जैसी अवधारणा के साथ समझा जा सकता है
अभी कोई टिप्पणी नहीं है.