تكنولوجيا

برمجة تعريفات الـ USB: توقف عن الخوف من النواة

كيف تبرمج تعريف جهازك الأول دون الدخول في تعقيدات Kernel

محرر أخبار تقنية في النيل نيوز، يهتم بتغطية المستجدات في عالم التكنولوجيا والإنترنت

يُشاع دائماً أن كتابة تعريفات الأجهزة (Drivers) هي نوع من السحر الأسود الذي يتطلب الغوص في أعماق النواة (Kernel) والتعامل مع لغات منخفضة المستوى ومعقدة. الحقيقة مغايرة تماماً؛ الأمر لا يتجاوز في صعوبته كتابة تطبيق بسيط يتعامل مع المقابس البرمجية (Sockets).

لنأخذ هاتف أندرويد في وضع «البوت لودر» (Bootloader) كمثال. لماذا؟ لأنه متاح، بروتوكوله بسيط، والأهم أن نظام التشغيل لن يتدخل في تجاربنا لأنه لا يملك تعريفاً مسبقاً له في الغالب.

عند توصيل أي جهاز USB، تبدأ عملية تسمى «Enumeration». هنا يسأل الحاسبُ الجهازَ: «من أنت؟». الجهاز يرد بمعرفين أساسيين: معرف البائع (VID) ومعرف المنتج (PID). بالمناسبة، الحصول على معرف بائع رسمي ليس مجانياً؛ تفرض منظمة USB-IF على الشركات رسوماً تصل إلى 5000 دولار سنوياً للحفاظ على معرف خاص بها، وهو ما يفسر لماذا تلجأ الشركات الصغيرة أحياناً لاستخدام معرفات مشتركة.

أداة مثل `lsusb` على لينكس تكشف لك المستور. ستجد أرقاماً مثل `18d1:4ee0`. الرقم الأول يخص جوجل، والثاني يخص وضع «الفاست بوت».

لماذا نبتعد عن النواة؟ ببساطة لأن مكتبة مثل `libusb` تسمح لنا بالتحكم في الجهاز من «مساحة المستخدم» (Userspace). هذا يعني أخطاء أقل، وسهولة في التصحيح، وعدم الحاجة لإعادة تشغيل النظام عند كل خطأ برمجي.

تخيل الـ Endpoints (نقاط النهاية) كأنها منافذ (Ports) في شبكة. هناك دائماً النقطة «0x00»، وهي القناة الموحدة للتحكم. لا تظهر هذه النقطة في قوائم التوصيف لأنها بديهية وموجودة في كل جهاز USB بموجب المعايير العالمية.

الاتصال ليس عشوائياً. هناك أنواع:
– Bulk: لنقل البيانات الضخمة (مثل الفلاش ميموري).
– Interrupt: للأجهزة التي تحتاج استجابة سريعة مثل الفأرة.
– Isochronous: لبث الصوت والفيديو حيث التوقيت أهم من دقة كل بت.

في وضع «الفاست بوت»، نستخدم نوع «Bulk». الهاتف ينتظر أمراً نصياً، ويرد برمز حالة من 4 أحرف.

عندما ترسل أمر `getvar:version` عبر نقطة النهاية (OUT Endpoint)، يقوم الهاتف بمعالجة الطلب. ثم، وباستخدام نقطة النهاية (IN Endpoint)، نقرأ الرد. تذكر دائماً: المضيف (الحاسب) هو السيد، والجهاز هو التابع. لا يمكن للجهاز أن يتحدث إلا إذا سأله الحاسب.

الكود البرمجي الذي ينفذ هذا الأمر لا يتجاوز بضعة أسطر باستخدام `libusb_bulk_transfer`. النتيجة ستكون غالباً `OKAY0.4`. هذا الرد يعني أن كل شيء يعمل. لقد تواصلت مع الأجهزة الصلبة مباشرة.

نقطة أخيرة لمن يستخدم ويندوز: قد تحتاج لأداة مثل Zadig لاستبدال التعريف الافتراضي بتعريف `WinUSB` لكي تتمكن مكتبة `libusb` من الوصول للجهاز. لينكس أكثر تسامحاً في هذا الجانب، طالما تملك الصلاحيات الكافية للوصول إلى منفذ الـ USB.

مقالات ذات صلة