من المترجم :
هذه ترجمة دليل البرمجة باستخدام PyUSB 1.0
تمت كتابة هذا الدليل من قبل مطوري PyUSB ، ولكن بسرعة من خلال الالتزامات ، أعتقد أن walac هو المؤلف الرئيسي للدليل.دعني أقدم نفسي
PyUSB 1.0 هي مكتبة
Python توفر سهولة الوصول إلى
USB . يوفر PyUSB وظائف مختلفة:
- 100٪ مكتوب بلغة Python:
على عكس إصدارات 0.x المكتوبة بلغة C ، الإصدار 1.0 مكتوب بلغة Python. هذا يسمح لمبرمجي Python الذين ليس لديهم خبرة C بفهم أفضل لكيفية عمل PyUSB. - حيادية المنصة:
يتضمن الإصدار 1.0 مخطط الواجهة الأمامية. يعزل API عن تفاصيل التنفيذ الخاصة بالنظام. تربط واجهة IBackend هاتين الطبقتين. يأتي PyUSB مزودًا بخلفية مدمجة لـ libusb 0.1 و libusb 1.0 و OpenUSB. يمكنك كتابة الواجهة الخلفية بنفسك إذا أردت. - قابلية:
يجب أن يتم تشغيل PyUSB على أي نظام أساسي به Python> = 2.4 ، وأنواع ، وواحد على الأقل من الخلفيات المدعومة. - البساطة:
لم يكن التفاعل مع جهاز USB بهذه السهولة من قبل! USB هو بروتوكول معقد ، ولدى PyUSB إعدادات مسبقة جيدة للتكوينات الأكثر شيوعًا. - دعم العتاد المتزامن:
يدعم PyUSB عمليات النقل المتزامنة إذا كانت الخلفية الأساسية تدعمها.
على الرغم من أن PyUSB يجعل برمجة USB أقل إيلاما ، إلا أن هذا البرنامج التعليمي يفترض أن لديك الحد الأدنى من المعرفة ببروتوكول USB. إذا كنت لا تعرف أي شيء عن USB ، فإنني أوصي بكتاب Jan Axelson
الممتاز USB Complete .
يكفي الحديث ، دعنا نكتب الرمز!
من هو من
للبدء ، دعنا نقدم وصفًا لوحدات PyUSB. جميع وحدات PyUSB تحت
USB ، مع الوحدات التالية:
الوحدة | الوصف |
---|
الأساسية | وحدة USB الرئيسية. |
استخدام | وظائف مساعدة. |
تحكم | طلبات الإدارة القياسية. |
تراث | طبقة توافق الإصدار 0.x. |
الخلفية | حزمة فرعية تحتوي على واجهات خلفية مدمجة. |
على سبيل المثال ، لاستيراد وحدة نمطية
أساسية ، أدخل ما يلي:
>>> import usb.core >>> dev = usb.core.find()
حسنًا ، لنبدأ
فيما يلي برنامج بسيط يرسل "اختبار" السلسلة إلى أول مصدر بيانات تم العثور عليه (نقطة النهاية OUT):
import usb.core import usb.util
يستورد أول سطرين وحدات حزمة PyUSB.
usb.core هي الوحدة الرئيسية ، ويحتوي
usb.util على وظائف المساعد. يبحث الأمر التالي عن جهازنا ويعيد نسخة من الكائن إذا وجد. إذا لم يكن كذلك ، بإرجاع
لا شيء . بعد ذلك ، نقوم بتعيين التكوين الذي سنستخدمه. ملاحظة: غياب الحجج يعني أن التكوين المرغوب تم تعيينه افتراضيًا. كما سترى ، فإن العديد من ميزات PyUSB لها إعدادات افتراضية لمعظم الأجهزة الشائعة. في هذه الحالة ، يتم تعيين التكوين الأول.
ثم نبحث عن نقطة النهاية التي نهتم بها. نحن نبحث عنه داخل الواجهة الأولى التي لدينا. بعد أن نجد هذه النقطة ، نرسل البيانات إليها.
إذا كنا نعرف عنوان نقطة النهاية مسبقًا ، يمكننا ببساطة استدعاء وظيفة
الكتابة لكائن الجهاز:
dev.write(1, 'test')
هنا نكتب سلسلة "اختبار" عند نقطة التوقف في العنوان
1 . سيتم مناقشة جميع هذه الوظائف بشكل أفضل في الأقسام التالية.
ما الخطب؟
كل وظيفة في PyUSB تطرح استثناء في حالة حدوث خطأ. إلى جانب
استثناءات Python القياسية ، تحدد
PyUSB usb.core.USBError للأخطاء المتعلقة بـ USB.
يمكنك أيضًا استخدام وظائف سجل PyUSB. ويستخدم وحدة
تسجيل الدخول . لاستخدامه ، قم بتعريف
متغير بيئة
PYUSB_DEBUG بأحد مستويات التسجيل التالية:
فادح ،
خطأ ،
تحذير ،
معلومات أو
تصحيح .
بشكل افتراضي ، يتم إرسال الرسائل إلى
sys.stderr . إذا أردت ، يمكنك إعادة توجيه رسائل السجل إلى ملف عن طريق تحديد متغير البيئة
PYUSB_LOG_FILENAME . إذا كانت قيمته هي المسار الصحيح للملف ، فستتم كتابة الرسائل هناك ، وإلا سيتم إرسالها إلى
sys.stderr .
اين انت
يتم استخدام وظيفة
find () في الوحدة
الأساسية للبحث عن الأجهزة المتصلة بالنظام وترقيمها. على سبيل المثال ، لنفترض أن جهازنا يحتوي على معرف بائع بقيمة 0xfffe ومعرف منتج 0x0001. إذا كنا بحاجة إلى العثور على هذا الجهاز ، فسنقوم بذلك:
import usb.core dev = usb.core.find(idVendor=0xfffe, idProduct=0x0001) if dev is None: raise ValueError('Our device is not connected')
هذا كل شيء ، ستقوم الوظيفة بإرجاع جهاز
usb.core.Device الذي يمثل جهازنا. إذا لم يتم العثور على الجهاز ، فسوف يعود بلا. في الواقع ، يمكنك استخدام أي حقل من فئة "
واصف الجهاز" الذي تريده. على سبيل المثال ، ماذا لو أردنا معرفة ما إذا كانت هناك طابعة USB متصلة بالنظام؟ من السهل جدا:
7 هو رمز لفئة الطابعة وفقًا لمواصفات USB. أوه ، انتظر ، ماذا لو أردت ترقيم جميع الطابعات المتاحة؟ لا مشكلة:
ماذا حدث حسنًا ، حان الوقت للحصول على شرح صغير ... تحتوي
find على معلمة تسمى
find_all وافتراضية لـ False. عندما تكون كاذبة
[1] ،
سيعثر الاكتشاف على أول جهاز يطابق المعايير المحددة (سنتحدث عنه قريبًا). إذا قمت بتمرير قيمة
حقيقية إلى المعلمة ،
فسيقوم Find بدلاً من ذلك بإرجاع قائمة بجميع الأجهزة المطابقة للمعايير. هذا كل شيء! بسيطة ، أليس كذلك؟
هل انتهينا؟ لا! لم أخبر كل شيء حتى الآن: تضع العديد من الأجهزة في الواقع معلومات الفصل الخاصة بها في Interface
Descriptor بدلاً من Device
Descriptor . لذلك من أجل العثور على جميع الطابعات المتصلة بالنظام ، سنحتاج إلى مراجعة جميع التكوينات ، بالإضافة إلى جميع الواجهات ، والتحقق مما إذا تم تعيين إحدى الواجهات على bInterfaceClass 7. إذا كنت
مبرمجًا مثلي ، فقد تتساءل: هل هناك أي طريقة أسهل لتنفيذ ذلك. الجواب: نعم هو كذلك. للبدء ، دعنا نلقي نظرة على الرمز الجاهز للعثور على جميع الطابعات المتصلة:
import usb.core import usb.util import sys class find_class(object): def __init__(self, class_): self._class = class_ def __call__(self, device):
تقبل المعلمة
custom_match أي كائن تم استدعاءه يتلقى كائن الجهاز. يجب أن يكون صحيحًا لجهاز مناسب وخطأ لجهاز غير مناسب. يمكنك أيضًا الجمع بين
custom_match وحقول الجهاز إذا كنت تريد:
نحن هنا مهتمون بطابعات المورد 0xfffe.
صف نفسك
حسنًا ، لقد وجدنا الجهاز الخاص بنا ، ولكن قبل التفاعل معه ، نود معرفة المزيد عنه. حسنًا ، تعرف ، التكوينات ، الواجهات ، نقاط النهاية ، أنواع تدفقات البيانات ...
إذا كان لديك جهاز ، يمكنك الوصول إلى أي حقل لوصف الجهاز كخصائص للكائن:
>>> dev.bLength >>> dev.bNumConfigurations >>> dev.bDeviceClass >>>
للوصول إلى التكوينات المتاحة في الجهاز ، يمكنك تكرار الجهاز:
for cfg in dev: sys.stdout.write(str(cfg.bConfigurationValue) + '\n')
بنفس الطريقة ، يمكنك تكرار التهيئة للوصول إلى الواجهات ، وكذلك تكرار الواجهات للوصول إلى نقاط التحكم الخاصة بها. يحتوي كل نوع من الكائنات على حقول واصف مطابق كسمات. الق نظرة على مثال:
for cfg in dev: sys.stdout.write(str(cfg.bConfigurationValue) + '\n') for intf in cfg: sys.stdout.write('\t' + \ str(intf.bInterfaceNumber) + \ ',' + \ str(intf.bAlternateSetting) + \ '\n') for ep in intf: sys.stdout.write('\t\t' + \ str(ep.bEndpointAddress) + \ '\n')
يمكنك أيضًا استخدام الفهارس للوصول العشوائي إلى الواصفات ، كما يلي:
>>>
كما ترون تحسب المؤشرات من 0. لكن انتظر! هناك شيء غريب في طريقة الوصول إلى الواجهة ... نعم ، أنت على حق ، يأخذ مؤشر التكوين سلسلة من قيمتين ، الأولى هي فهرس الواجهة ، والثانية هي إعداد بديل. بشكل عام ، للوصول إلى الواجهة الأولى ، ولكن مع الإعداد الثاني ،
سنكتب cfg [(0،1)] .
حان الوقت الآن لتعلم طريقة قوية للبحث عن الواصفات - وهي وظيفة
find_descriptor مفيدة. لقد رأينا ذلك بالفعل في مثال بحث الطابعة. يعمل
find_descriptor تقريبًا مثل
البحث ، باستثناء اثنين:
- يتلقى find_descriptor كمعلمة أولى واصف المصدر الذي ستبحث عنه.
- لا يوجد معلمة خلفية في ذلك [2] .
على سبيل المثال ، إذا كان لدينا واصف تكوين
cfg ، ونريد العثور على جميع الإعدادات البديلة للواجهة 1 ، فسنقوم بذلك:
import usb.util alt = usb.util.find_descriptor(cfg, find_all=True, bInterfaceNumber=1)
لاحظ أن
find_descriptor موجود في وحدة
usb.util . يقبل أيضًا معلمة
custom_match الموضحة سابقًا.
نتعامل مع عدة أجهزة متطابقةفي بعض الأحيان ، يمكنك توصيل جهازين متطابقين بجهاز كمبيوتر. كيف يمكنك التمييز بينهما؟ تأتي كائنات
الجهاز بسمتين إضافيتين ليستا جزءًا من مواصفات USB ، ولكنها مفيدة جدًا: سمات
الناقل والعنوان . بادئ ذي بدء ، تجدر الإشارة إلى أن هذه السمات تأتي من الخلفية ، وقد لا تدعمها الخلفية - في هذه الحالة يتم تعيينها على
لا شيء . ومع ذلك ، تمثل هذه السمات رقم ناقل الجهاز وعنوانه ، وكما قد تكون خمنت ، يمكن استخدامها للتمييز بين جهازين لهما نفس قيم السمات
idVendor و
idProduct .
كيف أعمل؟
بعد الاتصال ، يجب تكوين أجهزة USB باستخدام بعض الاستعلامات القياسية. عندما بدأت في دراسة مواصفات
USB ، شعرت بالإحباط بسبب الواصفات والتكوينات والواجهات والإعدادات البديلة وأنواع النقل وكل ذلك ... والأسوأ من ذلك كله ، لا يمكنك تجاهلها فقط: لا يعمل الجهاز بدون تعيين التكوين ، حتى إذا كان واحدًا! يحاول PyUSB أن يجعل حياتك بسيطة قدر الإمكان. على سبيل المثال ، بعد استلام كائن جهازك ، أولاً وقبل كل شيء ، قبل التفاعل معه ، تحتاج إلى إرسال طلب
ضبط set_configuration . إن معلمة التكوين لهذا الاستعلام التي تهمك هي
bConfigurationValue . لا تحتوي معظم الأجهزة على أكثر من تكوين واحد ، وتتبع قيمة التكوين التي تستخدمها أمر مزعج (على الرغم من أن معظم الشفرة التي رأيتها للتو مشفرة). لذلك ، في PyUSB ، يمكنك ببساطة إرسال طلب
set_configuration بدون وسيطات. في هذه الحالة ، سيقوم بتثبيت التكوين الأول الذي تم العثور عليه (إذا كان جهازك يحتوي على تكوين واحد فقط ، فلا داعي للقلق بشأن قيمة التكوين على الإطلاق). على سبيل المثال ، افترض أن لديك جهازًا مع واصف تكوين واحد ، وحقل bConfigurationValue الخاص به هو 5
[3] ، ستعمل الاستعلامات اللاحقة بنفس الطريقة:
>>> dev.set_configuration(5)
واو! يمكنك استخدام كائن
التكوين كمعلمة
لتعيين التكوين ! نعم ، لديه أيضًا طريقة محددة لتكوين نفسه في التكوين الحالي.
خيار آخر تحتاج إليه أو لن تحتاج إلى تكوينه هو خيار تغيير الواجهات. يمكن أن يكون لكل جهاز تكوين نشط واحد فقط في كل مرة ، ويمكن أن يكون لكل تكوين أكثر من واجهة واحدة ، ويمكنك استخدام جميع الواجهات في نفس الوقت. من الأفضل أن تفهم هذا المفهوم إذا كنت تفكر في الواجهة كجهاز منطقي. على سبيل المثال ، دعونا نتخيل طابعة متعددة الوظائف ، وهي في نفس الوقت طابعة وماسحة ضوئية. من أجل عدم تعقيد (أو على الأقل جعلها بسيطة قدر الإمكان) ، لنفترض أن لديه تكوين واحد فقط. لأن لدينا طابعة وماسحة ضوئية ، وللتكوين واجهتان: واحدة للطابعة وواحدة للماسح الضوئي. الجهاز ذو أكثر من واجهة يسمى جهاز مركب. عند توصيل الطابعة متعددة الوظائف بجهاز الكمبيوتر الخاص بك ، سيقوم نظام التشغيل بتحميل برنامجين مختلفين: أحدهما لكل جهاز طرفي "منطقي" لديك
[4] .
ماذا عن إعدادات الواجهة البديلة؟ شيء جيد سألته. تحتوي الواجهة على إعداد بديل واحد أو أكثر. تعتبر واجهة مع إعداد بديل واحد فقط بدون إعدادات بديلة
[5] . الإعدادات البديلة للواجهات كتكوين للأجهزة ، أي أنه بالنسبة لكل واجهة ، يمكنك الحصول على إعداد بديل نشط واحد فقط. على سبيل المثال ، تشير مواصفات USB إلى أنه لا يمكن أن يكون للجهاز نقطة تحقق متزامنة في تكوينه البديل الأساسي
[6] ، بحيث يجب أن يحتوي جهاز البث على إعدادين بديلين على الأقل ، مع وجود إعداد ثانٍ له نقطة تحقق متزامنة. ولكن ، على عكس التكوينات ، لا يلزم تكوين واجهات ذات تكوين بديل واحد فقط
[7] . يمكنك تحديد إعداد واجهة بديل باستخدام وظيفة
set_interface_altsetting :
>>> dev.set_interface_altsetting(interface = 0, alternate_setting = 0)
تحذيرتوضح مواصفات USB أنه يُسمح للجهاز بإرجاع خطأ إذا تلقى طلب SET_INTERFACE لواجهة لا تحتوي على إعدادات بديلة إضافية. لذلك إذا لم تكن متأكدًا من أن الواجهة تحتوي على أكثر من إعداد بديل واحد أو أنها تقبل طلب SET_INTERFACE ، فإن الطريقة الأكثر أمانًا هي استدعاء
set_interface_altsetting داخل كتلة المحاولة باستثناء ، كما هو الحال هنا:
try: dev.set_interface_altsetting(...) except USBError: pass
يمكنك أيضًا استخدام كائن
Interface كمعلمة دالة ، حيث يتم توريث
الواجهة ومعلمات Alternate_setting تلقائيًا من
حقلي bInterfaceNumber و
bAlternateSetting . مثال:
>>> intf = find_descriptor(...) >>> dev.set_interface_altsetting(intf) >>> intf.set_altsetting()
تحذيريجب أن ينتمي كائن
الواجهة إلى واصف التكوين النشط.
حدثني يا عزيزي
والآن حان الوقت لنفهم كيفية التفاعل مع أجهزة USB. يحتوي USB على أربعة أنواع من تدفقات البيانات: النقل الجماعي والنقل المتقاطع والنقل المتزامن ونقل التحكم. لا أخطط لشرح الغرض من كل خيط والفروق بينهما. لذلك ، أفترض أن لديك المعرفة الأساسية على الأقل بتدفقات بيانات USB.
دفق بيانات التحكم هو الدفق الوحيد الذي تم وصف هيكله في المواصفات ، والباقي ببساطة يرسل ويستقبل البيانات الأولية من وجهة نظر USB. لذلك ، لديك وظائف مختلفة للعمل مع تدفقات التحكم ، وتتم معالجة باقي التدفقات بنفس الوظائف.
يمكنك الوصول إلى دفق بيانات التحكم باستخدام طريقة
ctrl_transfer . يتم استخدامه لتدفقات (OUT) الصادرة والواردة (IN). يتم تحديد اتجاه التدفق بواسطة المعلمة
bmRequestType .
تتطابق المعلمات
ctrl_transfer تقريبًا مع بنية طلب التحكم. فيما يلي مثال على كيفية تنظيم دفق بيانات التحكم.
[8] :
>>> msg = 'test' >>> assert dev.ctrl_transfer(0x40, CTRL_LOOPBACK_WRITE, 0, 0, msg) == len(msg) >>> ret = dev.ctrl_transfer(0xC0, CTRL_LOOPBACK_READ, 0, 0, len(msg)) >>> sret = ''.join([chr(x) for x in ret]) >>> assert sret == msg
يفترض هذا المثال أن جهازنا يتضمن طلبين للتحكم في المستخدم يعملان كأنبوب استرجاع. ما تكتبه بالرسالة
CTRL_LOOPBACK_WRITE ، يمكنك أن تقرأ بالرسالة
CTRL_LOOPBACK_READ .
المعلمات الأربعة الأولى -
bmRequestType و
bmRequest و
wValue و
wIndex - هي حقول الهيكل القياسي لدفق التحكم. المعلمة الخامسة هي إما البيانات التي يتم نقلها لتدفق البيانات الصادرة أو عدد البيانات التي تتم قراءتها في الدفق الوارد. يمكن أن تكون البيانات المرسلة أي نوع من التسلسل ، والتي يمكن تغذيتها كمعلمة لإدخال طريقة
__init__ للصفيف . في حالة عدم نقل البيانات ، يجب تعيين المعلمة على بلا (أو 0 في حالة دفق البيانات الواردة). هناك معلمة اختيارية أخرى تشير إلى انتهاء مهلة العملية. إذا لم تجتزه ، فسيتم استخدام المهلة الافتراضية (المزيد عن هذا لاحقًا). في دفق البيانات الصادرة ، القيمة المرجعة هي عدد وحدات البايت المرسلة بالفعل إلى الجهاز. في الدفق الوارد ، تكون القيمة
المرتجعة صفيفًا بقراءة البيانات.
بالنسبة إلى التدفقات الأخرى ، يمكنك استخدام طرق
الكتابة والقراءة ، على التوالي ، لكتابة البيانات وقراءتها. لا داعي للقلق بشأن نوع الدفق - يتم اكتشافه تلقائيًا عن طريق عنوان نقطة التفتيش. في ما يلي مثال الاسترجاع ، بشرط أن يكون لدينا ماسورة استرجاع عند نقطة الإيقاف 1:
>>> msg = 'test' >>> assert len(dev.write(1, msg, 100)) == len(msg) >>> ret = dev.read(0x81, len(msg), 100) >>> sret = ''.join([chr(x) for x in ret]) >>> assert sret == msg
المعلمتان الأولى والثالثة هي نفسها لكلتا الطريقتين - هذا هو عنوان نقطة التحقق والمهلة ، على التوالي. المعلمة الثانية هي البيانات المرسلة (الكتابة) أو عدد وحدات البايت المراد قراءتها (قراءة). ستكون البيانات التي تم إرجاعها إما مثيل لكائن
صفيف لطريقة
القراءة أو عدد وحدات البايت المكتوبة لطريقة
الكتابة .
باستخدام إصدارات بيتا 2 ، بدلاً من عدد وحدات البايت ، يمكنك تمرير كائن
صفيف للقراءة أو
ctrl_transfer التي سيتم قراءة البيانات إليها. في هذه الحالة ، سيكون عدد وحدات البايت المراد قراءتها هو طول المصفوفة مضروبًا في قيمة
الصفيف .
في
ctrl_transfer ، تكون معلمة
timeout اختيارية. عندما
يتم حذف
المهلة ، يتم
استخدام خاصية
Device.default_timeout كمهلة تشغيل.
تحكم بنفسك
بالإضافة إلى وظائف
دفق البيانات ، توفر وحدة
usb.control وظائف تتضمن طلبات تحكم USB القياسية ،
وتحتوي وحدة
usb.util على وظيفة
get_string ملائمة تعرض على وجه التحديد واصفات الخط.
موضوعات إضافية
وراء كل تجريد عظيم إدراك عظيم
في السابق ، كان هناك
libusb فقط. ثم جاء libusb 1.0 وكان لدينا libusb 0.1 و 1.0. بعد ذلك ، أنشأنا
OpenUSB ونعيش الآن في
برج بابل بمكتبة USB
[9] . كيف يتعامل PyUSB مع هذا؟ حسنًا ، PyUSB هي مكتبة ديمقراطية ، يمكنك اختيار المكتبة التي تريدها. في الواقع ، يمكنك كتابة مكتبة USB الخاصة بك من الصفر وإخبار PyUSB باستخدامها.
تحتوي وظيفة
البحث على معلمة أخرى ، لم أخبرك عنها. هذه هي معلمة
الواجهة الخلفية . إذا لم تقم بنقله ، فسيتم استخدام إحدى الواجهات الخلفية المضمنة. الواجهة الخلفية هي كائن موروث من
usb.backend.IBackend ، وهو مسؤول عن تقديم خردة USB الخاصة بنظام التشغيل. كما كنت قد خمنت ، فإن libusb 0.1 المدمج ، libusb 1.0 ، و OpenUSB هي خلفية.
يمكنك كتابة الواجهة الخلفية الخاصة بك واستخدامها. فقط ترث من
IBackend وتمكين الطرق الضرورية. قد تحتاج إلى إلقاء نظرة على وثائق
usb.backend لفهم كيفية القيام بذلك.
لا تكن أنانيا
Python لديها ما نسميه
إدارة الذاكرة التلقائية . هذا يعني أن الجهاز الظاهري سيقرر متى سيتم تفريغ الأشياء من الذاكرة. تحت الغطاء ، تدير PyUSB جميع الموارد منخفضة المستوى التي تحتاج إلى العمل معها (الموافقة على الواجهة ، وتعديل الجهاز ، وما إلى ذلك) ولا يحتاج معظم المستخدمين إلى القلق بشأن هذا الأمر. ولكن ، بسبب الطبيعة غير المحددة للتدمير التلقائي للكائنات بواسطة Python ، لا يمكن للمستخدمين التنبؤ بموعد إصدار الموارد المخصصة. تحتاج بعض التطبيقات إلى تخصيص الموارد وتحريرها بشكل محدد. لمثل هذه التطبيقات ، توفر وحدة
usb.util وظائف للتفاعل مع إدارة الموارد.
إذا كنت ترغب في طلب واجهات
وتحريرها يدويًا ، يمكنك استخدام
وظيفتي Claim_interface و
release_interface .
ستطلب وظيفة Claim_interface الواجهة المحددة إذا لم يقم الجهاز بذلك بعد. إذا طلب الجهاز بالفعل واجهة ، فلن يفعل شيئًا. كما ستقوم release_interface بتحرير الواجهة المحددة ، إذا طلبت. إذا لم يتم طلب الواجهة ، فلن تفعل شيئًا. يمكنك استخدام الاستعلام اليدوي عن الواجهة لحل مشكلة اختيار التكوين الموضحة في وثائق libusb . إذا كنت تريد تحرير جميع الموارد المخصصة بواسطة كائن الجهاز (بما في ذلك الواجهات المطلوبة) ، يمكنك استخدام وظيفة dispose_resources. يقوم بتحرير جميع الموارد المخصصة ويضع كائن الجهاز (ولكن ليس في جهاز الجهاز نفسه) إلى الحالة التي تم إرجاعها فيها بعد استخدام وظيفة البحث .تعريف المكتبة اليدوي
بشكل عام ، تعتبر الواجهة الخلفية مجمّعة فوق مكتبة مشتركة تنفذ واجهة برمجة تطبيقات للوصول إلى USB. بشكل افتراضي ، تستخدم الخلفية وظيفة ctypes find_library () . في Linux وأنظمة التشغيل الأخرى المشابهة لـ Unix ، يحاول find_library تشغيل برامج خارجية (مثل / sbin / ldconfig و gcc و objdump ) للعثور على ملف المكتبة.في الأنظمة التي تفتقد هذه البرامج و / أو يتم تعطيل ذاكرة التخزين المؤقت للمكتبة ، لا يمكن استخدام هذه الوظيفة. للتغلب على القيود ، يسمح لك PyUSB بإرسال الوظيفة المخصصة find_library () إلى الواجهة الخلفية.مثال على هذا السيناريو سيكون: >>> import usb.core >>> import usb.backend.libusb1 >>> >>> backend = usb.backend.libusb1.get_backend(find_library=lambda x: "/usr/lib/libusb-1.0.so") >>> dev = usb.core.find(..., backend=backend)
لاحظ أن find_library هي وسيطة للدالة get_backend () ، حيث تقوم بتوفير الوظيفة المسؤولة عن إيجاد المكتبة الصحيحة للواجهة الخلفية.قواعد المدرسة القديمة
إذا كنت تكتب تطبيقًا باستخدام واجهات برمجة تطبيقات PyUSB القديمة (0. شيء ما هناك) ، فقد تسأل نفسك عما إذا كنت بحاجة إلى تحديث الرمز الخاص بك لاستخدام واجهة برمجة التطبيقات الجديدة. حسنًا ، يجب أن تفعل ذلك ، لكن هذا ليس ضروريًا. يأتي PyUSB 1.0 مزودًا بوحدة توافق usb.legacy . يتضمن واجهة برمجة التطبيقات القديمة القائمة على واجهة برمجة التطبيقات الجديدة. "حسنا، أنا فقط يجب أن يحل محل بلدي خط USB استيراد ل usb.legacy استيراد ك USB للحصول على طلبي للعمل؟"، تسأل. الجواب نعم ، ستعمل ، لكنها ليست ضرورية. إذا قمت بتشغيل التطبيق الخاص بك دون تغيير ، فسيعمل لأن خط استيراد USB يستورد جميع الرموز العامة من usb.legacy. إذا واجهت مشكلة - على الأرجح أنك وجدت خطأ.ساعدني من فضلك
إذا كنت بحاجة إلى مساعدة ، فلا تكتب لي بريدًا إلكترونيًا ، فهناك قائمة بريدية لهذا. يمكن العثور على تعليمات الاشتراك على موقع PyUSB .[1] عندما أكتب صح أو خطأ (بحرف كبير) ، أعني القيم المقابلة للغة بايثون. وعندما أقول صوابًا (صوابًا) أو خطأ (خطأ) ، أعني أي تعبير من لغة Python يُعتبر صحيحًا أو خطأ. (حدث هذا التشابه في الأصل ويساعد على فهم مفاهيم الصواب والخطأ في الترجمة. - ملاحظة. ) :[2] راجع الوثائق المحددة للواجهة الخلفية.[3] لا تفرض مواصفات USB أي قيمة محددة على قيمة التكوين. وينطبق الشيء نفسه على أرقام الواجهة والإعدادات البديلة.[4] في الواقع ، كل شيء أكثر تعقيدًا بعض الشيء ، ولكن هذا مجرد تفسير لنا.[5] أعلم أن هذا يبدو غريبًا.[6] هذا لأنه إذا لم يكن هناك عرض نطاق ترددي لتدفقات البيانات المتزامنة أثناء تكوين الجهاز ، فيمكن ترقيمها بنجاح.[7] لا يحدث هذا للتهيئة لأنه يُسمح للجهاز أن يكون في حالة غير مهيأة.[8] في PyUSB ، التحكم في وصول بيانات التحكم إلى نقطة التحكم في الوصول 0. نادرًا جدًا جدًا ما يكون للجهاز نقطة تحكم تحكم بديلة (لم أقابل مثل هذا الجهاز أبدًا).[٩] هذه مجرد مزحة ، لا تأخذها على محمل الجد. الخيارات العظيمة أفضل من عدم وجود خيارات.