نمایش/عدم نمایش سایدبار
رفتن به بالای صفحه
آزادی حجاز از دست نااهلان
مهدی دمیرچیلو

آموزش کلاس hid از پروتکل usb جلسه 1

به نام خدا : در این مطلب میخوام درباره کلاس HID توضیح بدم که ترجمه اسناد HID هستش؛ دستگاه هایی مثل موس، کیبورد، دسته بازی و … از این کلاس استفاده میکنند، مطالب اضافه دیتاشیت حذف شدند، چیدمان و ترتیب مطالب رو تغییر دادم تا فهم مطلب ساده تر بشه، ممکه بعضی قسمتا رو با رنگ صورتی مشخص کرده باشم که یعنی اونا متن خودم هستند و ممکنه سوال باشن/شک باشن/ترجمه مشکل دار باشن و … ( در کل اینا نیاز به بررسی دارند )

آموزش کلاس hid از پروتکل usb جلسه 1

آموزش کلاس hid از پروتکل usb جلسه 1

توجه : Human Interface Device مخففش HID میشه.

 

کاربردهای کلاس HID

کاربردهای کلاس HID

  1. Keyboard
  2. mouse
  3. trackball ( یه جور دسته بازی هستش، این فیلم رو ببینید : USB Trackball )
  4. joystick ( اینم یه مدل دسته بازی هستش و نیازی به معرفی نداره! )
  5.  Knob ( یه جور کنترل ولوم هستش، این فیلم رو ببینید : Usb Control Knob )
  6. Barcode reader
  7. RFID reader ( مثلا یه مدل RFID ها هستند که شبیه کیبورد عمل میکنند برای انتقال دیتا، مثلا هر موقع کارتی سنس کنند، دیتا رو ارسال میکنند و اگه شما داخل مثلا notepad باشید کد خونده شده همونجا paste میشه، دقیقا مثل کیبورد که هرجا کلیدی رو فشار بدی، اون کاراکتر همونجا paste میشه )
  8. buttons / switches
  9. sliders
  10. و ...

 

توضیحات ابتدایی

توجه : یک روش ساده برای شناسایی پروتکل دستگاه برای دستگاه هایی که نیاز به پشتیبانی از BIOS دارند (دستگاه های بوت) مورد نیاز است؛ دستگاه های کلاس HID از قسمت Subclass برای نشان دادن دستگاه هایی که از یک پروتکل از پیش تعریف شده برای هر دو دستگاه موس یا صفحه کلید پشتیبانی می کنند (یعنی دستگاه می تواند به عنوان یک دستگاه بوت استفاده شود) استفاده شود. ( لپ کلوم این که در کلاس HID از قسمت Subclass برا تعیین این که "پروتکول دستگاه از پیش تعریف شده هستش یا نه، اگه باشه که در مد BOOT میتونه کار کنه" استفاده میشه )

 

Controll pipe و Interrupt pipe : کلاس HID از دو pipe استفاده میکنه یکی Controll pipe ( که برا راه اندازی و پیکربندی و... بکار میره ) و دیگری Interrupt pipe ( که برا بحث تبادل داده بین دستگاه و میزبان بکار میره )

HID pipe

Interrupt pipe میتونه از دو Endpoint ورودی و یا خروجی استفاده کنه که EP IN وجودش ظرورری و EP OUT اختیاری هستش ( مثلا موس فقط دیتا میفرسته به PC ولی دستگاه بازی، هم دیتا میفرسته و هم دیتا میگیره، مثلا اون شوک دسته بازی که از PC دیتا میگیره تا کی شوک فعال بشه و کی غیرفعال )؛ کلاس HID از Controll pipe برا ارسال داده استفاده میکنه به صورت پیشفرض؛ ولی خب من باشم از یه Interrupt pipe برای اینکار استفاده میکنم.

 

تجزیه Item ها : HID class driver حاوی یک تجذیه کننده هستش که برا آنالیز item های پیدا شدن در Report descriptor مورد استفاده قرار میگیره؛ تجزیه کننده اطلاعات را از descriptor به صورت خطی استخراج می کند؛ تجزیه کننده وضعیت هر item شناخته شده را از طریق descriptor جمع آوری می کند و آنها را در یک جدول وضعیت item ذخیره می کند؛ جدول وضعیت item حاوی وضعیت item های خاصی است.

از دید تجزیه کننده، یک HID class device چیزی شبیه عکس زیر هستش :

HID class device from the parser point of view

هنگامی که با برخی از item ها مواجه میشود ( احتمالا تجزیه کننده رو میگه )، محتوایت جدول وضعیت item جابجا شده است، این item ها حاوی تمام Main و Push و Pop آیتم ها هستند. ( بررسی ترجمه )

1) هنگامی که یک Main item یافت می شود، یک ساختار report جدید اختصاص داده می شود و با جدول وضعیت فعلی item ها راه اندازی می شود؛ سپس همه item های محلی از جدول وضعیت item حذف می شوند، اما Global item ها باقی می مانند؛ به این ترتیب Globad item ها مقدار پیشفرض برا Main item های بعدی را تنظیم میکنند؛ یک دستگاه با چندین کنترل مشابه مانند شش محور ( یه بازوی رباتی رو درنظر بگیرید که از 6 تا سروو موتور تشکیل شده )، نیاز دارد که تنها یکبار قبل از اولین Main item بیاد و Global item ها رو تعریف کند.

توجه : Main item ها به مجموعه ای که در آن به ترتیب تعریف شده اند، مرتبط هستند؛ یک Collection جدید زمانی شروع می شود که تجزیه کننده به یک item Collection برسد؛ تجذیه کننده item با مجموعه تمام Main item ها که بین Collection item و انتهای Collection item بعدی تعریف شده اند، مرتبط هستند.

2) هنگامی که با یک Push item مواجه می شود، جدول وضعیت item کپی می شود و برای بازیابی بعدی در یک stack قرار می گیرد.

3) وقتی که یک Pop item پیدا میشود، جدول وضعیت item با جدول بالا از Stack جایگزین میشه، برای مثال :

Unit (Meter), Unit Exponent (-3), Push, Unit Exponent (0)

هنگامی که تجزیه کننده به یک Push item میرسد، item های تعیین کننده واحدهای میلی متر را در stack قرار می دهد؛ item بعدی، جدول وضعیت item را به واحد متر تغییر می دهد.

تجذیه کننده برا تجذیه و تحلیل ( آنالیز ) Report descriptor دریافتی از دستگاه، مورد نیاز هستش تا تمام Mian item ها رو پیدا کنه.

 

Usages ( کاربرد ها ) : Usage ها بخشی از Report descriptor هستند و یک توسعه دهنده نرم افزار را با اطلاعاتی در مورد آنچه که در واقع اندازه گیری کنترل است ارائه می دهد؛ علاوه بر این، یک Usage tag مشخص میکنه vendor پیشنهادی جهت استفاده برای یک control خاص یا گروهی از control ها؛ در حالی که Report descriptor ها، فرمت داده ها را توصیف می کنند، به عنوان مثال، سه فیلد 8 بیتی، یک Usage tag تعریف میکند که چه باید با داده ها انجام شود، به عنوان مثال، ورودی x، y و z؛ این ویژگی به vendor اجازه می دهد اطمینان حاصل کند که کاربر تخصیص تابع تطبیق پذیر را برای کنترل در میان برنامه ها انجام می دهد.

یک Report descriptor میتونه چندین Usage tag داشته باشه؛ یک رابطه یک به یک بین usage ها و control ها وجود دارد، یک usage control در descriptor تعریف شده است؛ یک آرایه نشان می دهد که هر فیلد یک Report descriptor، نشان دهنده چندین physical control است؛ هر control ممکن است attribute هایی مانند usage اختصاصی به آن داشته باشد؛ برای مثال، یک آرایه از چهار دکمه می تواند یک Usage tag منحصر به فرد برای هر دکمه داشته باشد.

یک Usage به عنوان مقدار 32 بیتی بدون علامت تفسیر می شود که در آن 16 بیت بالا به عنوان Usage Page تعریف شده اند و 16 بیت پایین به عناون Usage ID تعریف شده اند؛ Usage ID ها برای انتخاب یک Usage خاص از یک Usage Page مورد استفاده قرار میگیرند.

 

Reports : یک دستگاه میتونه ارسال/دریافت کنه یک transcation رو در هر فریم (1ms)؛ هر ترنزکشن هم ممکنه حاوی چندین پکیج باشه؛ که یک transfer حاوی چند ترنزکشن هستش مثلا : گزارش ( Report ) ورودی، خروجی و ویژگی ها؛ در این سند، یک transfer معادل با یک report هستش.

HID Reports

اکثر دستگاه ها report ها ( transfer ها ) رو توسط return کردن یک ساختار در هر فیلد دیتا که به صورت متناوب نشان داده میشود تولید میکنند؛ با این حال، بعضی دستگا ها ممکنه چندین ساختار report چندگانه ای در یک endpoint داشته باشند، که هر یک فقط تعدادی ا فیلد های داده رو نشون میدن؛ برای مثال، یک کیبورد با یک دستگاه اشاره گر یکپارچه ( فک کنم همچین دستگاهی منظورشه، این فیلم رو ببینید : keyboard with an integrated pointing ) میتواند به صورت مستقل ( سرخود ) داده "key press" و "pointing" رو report کنه توسط یک endpoint یکسان ( خلاصش میشه : یعنی دیتای 2 تا چیز مختلف رو توسط یک endpoint ارسال کنه، این قابلیت رو داره )؛ item های Report ID برای نشان دادن اینکه کدام فیلد داده در هر ساختار گزارش نمایش داده می شوند استفاده می شود؛ یک Report ID item tag یک پیشوند شناسایی 1 بایتی برای هر report اختصاص می دهد؛ اگر هیچ Report ID item tag یی در Report descriptor وجود نداشت، می توان فرض کرد که تنها یک ساختار گزارش ( Report ) ورودی، خروجی و ویژگی وجود دارد و با هم تمام داده های دستگاه را نشان می دهند.

توجه : فقط گزارش های ورودی از طریق وقفه در لوله ارسال می شود. گزارش های ویژگی ها و خروجی ها باید توسط میزبان از طریق لوله کنترل یا لوله وقفه خروجی اختیاری آغاز شوند.

اگر یک دستگاه دارای ساختار گزارش چندگانه باشد، تمام انتقال داده ها با یک پیشوند شناسه 1-بایتی آغاز می شود که نشان می دهد که کدام ساختار گزارش برای انتقال استفاده می شود؛ این اجازه می دهد تا class driver تمایز داده های اشاره گر دریافتی را از داده های صفحه کلید با بررسی پیشوند انتقال.

 

Strings : یک فیلد دیتا و یا collection میتونه label مخصوص به خودشو داشته باشه ( string index )، در ضمن string ها اختیاری هستند.

Usage tag یک item همانند string مربوط به Main item وجودشون ظروری نیست؛ با این حال، string ها ممکن است مفید باشند وقتی که یک vendor-defined usage مورد نیاز هستش؛ String descriptor ها حاوی لیستی از text string ها برای دستگاه هستند.

 

Orientation ( جهت / گرایش ) : دستگاه های HID کلاس، در صورت امکان، تشویق می شوند تا از یک سیستم مختصات دست راست استفاده کنند؛ اگر یک کاربر با یک دستگاه مواجه شود، مقادیر گزارش باید از طرف چپ به راست (X)، از دور تا نزدیک (Y) و از بالا به پایین (Z) افزایش یابد.

HID Orientation

گزارش کنترل داده های باینری باید از کنوانسیون 0 = off/false و 1 = on/true استفاده کنند؛ نمونه هایی از این کنترل ها عبارتند از کلید، دکمه، سوئیچ قدرت و سنسور مجاورت دستگاه.

 

مقادیر null : دستگاه های کلاس HID قادر به نادیده گرفتن فیلد های انتخاب شده در یک گزارش در زمان اجرا هستند؛ این کار با اعلام bit field در یک گزارش انجام شده است که قادر به حاوی طیف وسیعی از مقادیر بزرگتر از آنچه که واقعا توسط کنترل ایجاد شده است؛ اگر میزبان یا دستگاه یک مقدار خارج از محدوده دریافت می کند، مقدار فعلی برای کنترل مربوطه تغییر نخواهد کرد.

یک توسعه دهنده سخت افزار باید کنترلها را در یک گزارش شخصی ارزیابی کند تا تعیین شود که چگونه یک برنامه در میزبان از آنها استفاده کند؛ اگر هر موقعیتی وجود دارد که در آن برنامه هر بار که گزارش به دستگاه ارسال می شود، یک فیلد خاص را بخواد تغییر بده، اونوقت فیلد باید حاوی مقدار null باشد؛ با استفاده از مقادیر Null، میزبان می تواند تمام فیلدهای را در یک گزارش که نیازی به تغییر به مقدار null (خارج از محدوده) ندارند، راه اندازی کند و زمینه هایی را که مایل است تغییر دهد به مقادیر معتبر (در محدوده) تعیین می کند.

اگر یک فیلد 8 بیتی اعلام شود و محدوده مقادیر معتبر 0 تا 0x7F باشد، هر مقدار بین 0x80 و 0xFF، خارج از محدوده درنظر گرفته می شود و در هنگام دریافت، نادیده گرفته می شود. مقدار اولیه مقادیر null در یک گزارش خیلی ساده تر است اگر همه آنها یکسان باشند.

توجه : به شدت توصیه می شود که 0 در مجموعه ای از مقادیر Null گنجانده شود به طوری که بافرهای گزارش می توانند به سادگی به صفر برای ایجاد حالت "مراقبت" برای همه فیلدها تنظیم شوند. ( میگه برا مقادیر null از مقدار استاندارد 0 استفاده کنید و مقادیر دلخواه دیگه ای تعریف نکنید براش! )

 

Descriptor های مختص کلاس HID

لیست Descriptor های دستگاه یی که از کلاس HID استفاده میکنه : 

در عکس زیر میبینید که غیر از Descriptor های استاندارد باید Descriptor های کلاس HID رو هم داخل دستگاه تعریف کنیم.

توجه : دستگاه هایی که از کلاس HID استفاده میکنند معمولا از یک configuration استفاده میکنند ( و بطبع دارای یک Configuration descriptor هستند )

لیست Descriptor های دستگاه HID

توجه : دستگاه های USB یی که نیاز به داده با رنج خارج از محدوده کلاس داشته باشند باید class specifications و درایور مختص خودشونو داشته باشند ( چطوری؟ یعنی چی؟ )

توجه : یک دستگاه USB ممکن است از یک نوع کلاس تشکیل شده باشد و یا از چندین کلاس مختلف، مثلا یک telephone ( که با پورت USB به کامپیوتر وصل میشه ) نیاز داره که از سه کلاس HID و Audio و Telephony استفاده کنه، که این امر شدنی هستش ( زیرا کلاس ها در Interface descriptor تعریف میشوند و نه Device descriptor ها که فقط میتونیم یه دونه ازش داشته باشیم / به تعداد مورد نیاز میتونیم Interface descriptor داشته باشیم )

 

Descriptor های مختص کلاس HID

در مطلب آموزش USB، توضیح دهنده های استاندارد ( Device و Configuration و Interface و Endpoint و String ) رو توضیح دادیم، اکنون میخوایم به توضیح "Descriptor های مختص کلاس HID" بپردازیم؛ هر کلاس دستگاه شامل یک یا چند توصیف کننده کلاس خاص است، این توصیفگرها از توصیفگرهای استاندارد USB متفاوت هستند، یک دستگاه کلاس HID، میتونه حاوی 3 نوع Descriptor زیر باشه ( گفتم 3 نوع، نگفتم 3 تا، دقت کنید ) :

  1. HID
  2. Report
  3. Physical

 

در زیر فیلدهای bLength و bDescriptorType که بین این 3 تا Descriptor ( مختص کلاس HID ) مشترک هستند رو مختصرا توضیح میدم و فیلد های Class/SubClass/Protocol رو هم توضیح میدم :

 

فیلد bLength : بیان گر تعداد بایت های اون Descriptor هستش.

 

فیلد bDescriptorType ( مختص Descriptor های کلاس HID ) : در مطلب "آموزش پروتکل usb" گفتم که فیلد دوم هر Descriptor یی، bDescriptorType هستش که نوع Descriptor رو مشخص میکنه، در اون مطلب لیست مقادیر فیلد bDescriptorType که مربوط به Descriptor های استاندارد بودند رو گزاشتم، در زیر لیست مقادیر مربوط به Descriptor های کلاس HID رو مشاهده میکنید ( که این مقادیر به فیلد bDescriptorType داده میشه ) :

HID Class bDescriptorType

 

فیلد bDeviceClass/bInterfaceClass : برای کلاس HID برابر مقدار ثابت 3 هستش.

 

فیلد bDeviceSubClass/bInterfaceSubClass : مقادیری که این فیلد میتونه بگیره به صورت زیر هستش :

0 : دستگاه در مد BOOT کار نمیکنه.
1 : دستگاه در مد BOOT کار میکنه.
2 تا 255 : رزرو شده.

 

فیلد bDeviceProtocol/bInterfaceProtocol : ان فیلد تنها زمانی مورد استفاده قرار میگیره که مقدار SubClass برابر 1 باشه ( دستگاه در مد BOOT کار میکنه )، فلذا به کمک این فیلد میایم تعیین میکنیم که دستگاه ما موس هستش یا کیبورد، در غیر این صورت باید مقدارش 0 باشه، انواع مقداری که این فیلد میتونه بگیره به صورت زیر هستش :

0 : هیچ کدام
1 : Keyboard
2 : Mouse
3 تا 255 : رزرو شده.

1) HID Descriptor

1) HID Descriptor

توصیف کننده HID، طول و نوع Physical Descriptor ها و Report Descriptor را برای یک دستگاه مشخص می کند ( طول و نوع خودشو رو همون اول مشخص میکنند، بعد نسخه سند HID که ازش استفاده میکنیم و بعد شماره کشور و بعد تعداد Descriptor ها رو تعیین میکنیم، بعد میریم سراغ طول و نوع Descriptor های دیگه ) :

HID Descriptor

bcdHID ( دو بایت) : بیانگر نسخه سندی هستش که ازش داریم استفاده میکنیم ( چیزی که من فهمیدم، شبیه bcdUSB که در مطلب "آموزش پروتکول UB" قسمت "Standard Device Descriptor" توضیح دادمش )

bCountryCode ( یک بایت) : کد کشوری که قراره دستگاه درش کار کنه؛ اکثر دستگاه ها، ازش استفاده نمیکنن ( مقدارشو 0 میزارن ) ولی خب مثلا تو کیبورد برا بحث کلید Caps میتونه مفید باشه؛ مقدار این فیلد به کمک جدول زیر تعیین میشه :

HID bCountryCode

bNumDescriptors ( یک بایت ) : این فیلد تعداد descriptor های کلاس HID رو مشخص میکنه ( که همیشه حداقل مقدارش 1 هستش، برای Report descriptor )

bDescriptorType ( یک بایت ) و wDescriptorLength ( دو بایت ) : همون طور که در بالا گفتم، ما حداقل باید از یک descriptor کلاس HID که Report descriptor هستش باید استفاده کنیم ( باید تعریفش کنیم در پروژمون - اینطور بگم بهتر هستش )، ولی خب چون در Report descriptor فیلد bLength ( برا تعیین تعداد بایت های descriptor فوق ) و فیلد bDescriptorType ( برا تعیین نوع descriptor ) وجود ندارد، فلذا اینجا مجبوریم اینکارو انجام بدیم، کد زیر رو ببینید، که مربوط به یک Report descriptor برا موس هستش؛ همون طور که میبینید هیچ این descriptor دو فیلدی که گفتم رو نداره ( متاسفانه ) :

توجه : با توجه به توضیحات فیلد bNumDescriptors، اگه بیش از یک Report descriptor ( یا انواع دیگه ) داشته باشیم، باید به تعداد descriptor ها از فیلد bDescriptorType و wDescriptorLength برا تعیین نوع و تعداد بایت هاش استفاده کنیم، برا همین در عکل بالا این دو فیلد رو داخل  [ ] گزاشته ( که یعنی تعداد اینا، بستگی به تعداد descriptor های کلاس داره ) - چیزی که فهمیدم رو سعی کردم به بهترین وجه توضیح بدم، شاید اشتباه هم گفته باشم!

2) Report Descriptor

2) Report Descriptor

Report descriptor برخلاف دیگر توضیح دهنده ها یک جدول داده ساده نیست!؛ طول و محتوای یک Report descriptor، خیلی متفات هستش بسته به تعداد فیلدهای داده مورد نیاز گزارش یا گزارش دستگاه متفاوت است؛ Report descriptor از مواردی است که اطلاعات مربوط به دستگاه را ارائه می دهند؛ بخش اول یک item حاوی سه فیلد است : item type و item tag و item size؛ این فیلد ها در کنار هم، نوع اطلاعاتی را که item فراهم می کند شناسایی می کند.

Report descriptor یک توضیح درباره دیتای فراهم شده توسط هر کنترل در یک دستگاه فراهم کرده؛ هر نوع Main item tag ( ورودی/خروجی/ویژگی ) مشخص کرده اندازه دیتای برگشت داده شده توسط یک کنترل خاص و مشخص کرده که آیا دیتا مطلق هستش یا نسبی و سایر اطلاعات مرتبط؛ item های پیشین Local و Global حداقل و حداکثر داده ها را تعریف می کنند و غیره؛ یک Report descriptor مجموعه کاملی از تمام item ها برای یک دستگاه است؛ با یک نگاه به یک Report descriptor تنها، برنامه کاربردی می داند که چگونه اطلاعات ورودی را پردازش می کند، و همچنین آنچه که داده ها می تواند مورد استفاده قرار گیرد.

یک یا چند فیلد داده از کنترل ها توسط یک Main item تعریف شده و توسط آیتم های قبلی Global و Local شرح داده می شود؛ Local item ها تنها فیلد های داده رو توضیح میدن که در Main item بعدی تعریف شده؛ Global item ها به attribute های پیش فرض برای همه فیلد های داده بعدی در آن توصیفگر تبدیل می شوند؛ به عنوان مثال، موارد زیر را بررسی کنید ( جزئیات برای خلاصه شدن حذف شده است ) :

Report Size (3)
Report Count (2)
Input
Report Size (8)
Input
Output

تجزیه کننده item های Report descriptor را در بالا تفسیر می کند و گزارش های زیر را ایجاد می کند ( LSB در سمت چپ ) :

input and output report fields

یک Report descriptor ممکنه حاوی چندین Main item باشه، یک Report descriptor حاوی هریک از item های زیر برای توضیح یک داده کنترل باشد ( همه item های دیگر اختیاری هستند ) :

  • (Input (Output or Feature
  • Usage
  • Usage Page
  • Logical Minimum
  • Logical Maximum
  • Report Size
  • Report Count

در زیر یک نمونه کدگذاری item ها که برای تعریف 3 دکمه ماوس استفاده می شود رو مشاهده میکنید؛ Main items ها به ترتیب از Global item ها مانند Usage، و Report Count یا Report Size (هر خط یک item جدید است) جلوتر هستند :

coding sample 3-button mouse

 

Items Types and Tags : هر item یک قطعه اطلاعاتی درباره دستگاه هستش، همه item ها 1-بایت پیشوند دارند ( چون بایت 0 هستش گفته پیشوند! ) که بیانگر نوع اساسی item است ( حاوی فیلدهای bSize و bType و bTag هستش )؛ کلاس HID دو قالب اساسی برای item ها را تعریف می کند :

Short items ( آیتم های کوتاه ) : در مجموع 1 تا 5 بایت طول دارند؛ عموما برای اکثر item هایی که رخ میدن مورد استفاده قرار میگیره؛ Short item معمولا حاوی 1 یا 0 بایت داده اختیاری هستند.

Long items ( آیتم های طولانی ) : 3 تا 258 بایت طول دارند؛ برا item هایی که نیاز به ساختار دیتای بزرگتری برای part ها دارند مورد استفاده قرار میگیره.

توجه : این سند تنها item هایی که از فرمت کوتاه استفده میکنند رو تعریف میکند، 2 فرمت item نباید با انواع item از قبیل Main و Global و Local اشتباه گرفته شوند

 

Short Items : بایت اول حاوی فیلد های bSize و bType و bTag هستش؛ بعد از این بایت، ممکنه 0،1،2 و یا 4 بایت دیتا قرار بگیره. ( که بستگی به فیلد bSize داره، عکس زیر برا وقتی هستش که 2 بایت دیتا داریم )

Generic Item Format

بایت 0 : حاوی فیلد های زیر هستش :

فیلد bSzie : تعیین تعداد بایت های داده.
فیلد bType : تعیین نوع item.
فیلد bTag : مشخص کننده عملکرد آیتم ( در ادامه مطلب و در قسمت توضیح هر یک از item ها، این فیلد رو هم به صورت کامل توضیح میدیم )

bSize bType
0 = 0 byte
1 = 1 byte
2 = 2 byte
3 = 4 byte
0 = Main
1 = Global
2 = Local
3 = Reserved

بایت های بعدی ( data ) : این بایت ها اختیاری هستند ( تعداد بایت هاشون توسط فیلد bSize ا بایت 0 تعیین میشه )

 

مطلب جلسه بعد

در زیر من 3 نوع کلی فیلد bTag رو توضیح میدم ولی در این مطلب توضیح ندادم که انواع ترکیب این 3 فیلد، و بایت/بایتهای بعدش حاوی چی هستش و چیکار میکنه، این خودش یه دیتاشیت 168 صفحه ای هستش ( دیتاشیت اصلی آموزش HID حدود 97 صفحه هستش! )، البته این 168 صفحه بیشترش جدوله، از تعداد صفحاتش نترسید خخخخ در مطلب جلسه بعد به این موضوع میپردازم.

 

توجه : فرمت تعریف Report Descriptor به صورت Short Items هستش؛ این مورد رو با فرمت مطرح شده در قسمت Report Protocol قاطی نکنید لطفا.

 

Long Items : همانند آیتم های کوتاه، در آیتم بلند هم در بایت اول 3 فیلد bSize و bType و bTag رو داریم ولی خب همونطور که میبینید مقدارشون ثابت هستش و در دو بایت بعدی ( bLongItemTag و bDataSize ) میایم و Tag و Size رو تعیین میکنیم ( که به این طریق مشخص میکنه که یک Long Item هستش )؛ بعد از این 3 بایت، میتونیم 255 بایت دیتا داشته باشم که تعداد این بایت های دیتا توسط بایت bDataSize تعیین میشه.

long item

توجه : هیچ نوع long item tag یی در این سند تعریف نشده است، این tag ها برای استفاده در آینده رزرو شده اند، تگهای 0xF0 تا 0xFF برای vendor تعریف شده اند.

2.1) Main Items

2.1) Main Items

این Main item ها برای استفاده یا تعریف گروه خاصی از انواع خاصی از type های داده در یک Report descriptor استفاده می شود؛ دو نوع Main item وجود دارد : داده ها و غیر داده ها؛ نوع داده Main item ها جهت ایجاد یک فیلد در داخل یک report مورد استفاده قرار میگیرند و شمال ورودی/خروجی/ویژگی هستش؛ item های دیگر فیلد ها رو ایجاد نمی کنند و متعاقبا به عنوان Main item غیر-داده نامیده می شوند.

اگه از Short Items استفاده میکنیم و فیلد bType رو روی Main تنظیم کردیم، مقدار فیلد bTag به کمک جدول زیر تعیین میشه ( خودم اضافه کردم این خط رو ) :

Main item tag

در جدول بالا میبینید که فیلد bTag یکی از 4 مقدار زیر رو میتونه بگیره :

  1. Input = 0b1000
  2. Output = 0b1001
  3. Feature = 0b1011
  4. Collection = 0b1010
  5. End Collection = 0b1100

توجه 1 : تو بایت 0 ( بایت پیشوند / Prefix )، بیت 0 و 1 ( فیلد bSize ) رو میبینید که مقدارشون nn هستش، که این 2 بیت برا تعیین تعداد بایت های داده بکار میره؛ بیت 2 و 3 ( فیلد bType ) رو هم میبینید که 00 هستند، چون الان در قسمت "Main Items" هستیم و این فیلد باید 00 باشه.

توجه 2 : مقادیر 0b110100nn تا 0b111100nn برای bTag رزرو شده هستند.

1) Input item tag : اشاره به دیتا از یک یا چند کنترل های مشابه در یک دستگاه داره؛ برای مثال، دیتای متغییر مانند خوندن موقیت یک تک محور یا گروهی از اهرم ها یا آرایه ای از اطلاعات مانند یک یا چند push button یا switch ها. ( لپ کلوم، برا خوندن اطلاعات از دستگاه )

2) Output item tag : اشاره به دیتا از یک یا چند کنترل های مشابه در یک دستگاه داره؛ برای مثال، تنظیم موقعیت یک محور ( سروو موتور فرض کنید ) یا گروهی از اهرم ها ( دیتا متغییر هستش ) یا تنظیم ( آرایه ای از اطلاعات ) یک یا چند LED ( لپ کلوم، تنظیم اطلاعات دستگاه، مثلا روشن خاموش کردن LED های دستگاه و .... )

3) Feature item tag : ورودی و خروجی دستگاه را برای کاربر نهایی برای مصرف در نظر نمی گیرد برای مثال، یک ویژگی نرم افزاری یا کنترل پنل را انتخاب کنید. ( نفهمیدم )

4) Collection item tag : یک گروه معنا دار از آیتم های وردی/خروجی/ویژگی، برای مثال، موس، کیبورد، جوی استیک و pointer

5) End Collection item tag : پایان دادن به آیتم مورد استفاده قرار میگره جهت مشخص کردن پایان یک مجموعه از item ها.

در جدول بالا میبیند که به کمک بایت های داده، نوع داده رو تعیین میکنیم.

توجه : مقدار پیشفرض بایت دیتا، برای تمام Main item ها صفر هستش.

توجه : یک Input item میتونه بایت دیتا نداشته باشه و فیلد bSize اش صفر باشه.

 

در ادامه مطلب، میریم سراغ توضیح این که فیلد داده چطور مقدار دهی میشه، یکم توضیح بیشتر بدیم...

 

Input/Output/Feature item tag

در این قسمت انواع مقداردهی بایت های داده رو با هم میبیینم و همونطور که قبلا گفتم، اینجا یکم بیشتر میخوایم توضیح بدیم، در قسمت قبلی درباره انواع مقدار دهی بایت های داده توضیحی ندادیم...

بیت صفر، (Data(0) | Constant(1 : نشان می دهد که item داده یا یک مقدار ثابت است؛ Data نشان می دهد که item یک report fields تعریف میکنه که حاوی داده های دستگاه قابل تغییر است؛ Constant نشان می دهد که item یک فیلد فقط خواندنی استاتیک در یک گزارش است و نمی تواند توسط میزبان اصلاح ( ویرایش ) شود.

چیزی که من فهمیدم : خود دستگاه هم نمیتونه مقدار item های که از نوع Constant هستند رو تغییر بده، چون خودش تعریف کرده که مقدارشون ثابت و غیر قابل تغییر هستند، درواقع اگه بگم داده های بدون کاربرد اشتباه نگفتم، مثلا تو موس 3 بایت داده داریم، که ارسال میکنه به میزبان، کلید های چپ/راست/وسط که میشن 3 بیت، در بایت اول ارسال میشن، حرکت موس در محور X و Y هر کدوم 2 بایت نیاز دارند، اما یه موردی، در بایت اول فقط از 3 بیت اولش استفاده شده، 5 بیت بعدی این بایت چی میشه؟ خب از نوع Constant تعریف میشه و مقدارشونو 0 میدیه دستگاه.

بیت یک، (Array(0) | Variable(1 : مشخص میکنه که item در report هاش یک متغییر ایجاد میکنه یا یک آرایه؛ در فیلدهای متغیر، هر فیلد داده ها نشان میده دیتا رو از یک کنترل فیزیکی؛ تعداد بیت هایی که برای هر فیلد اختصاص داده شده است، توسط مقادیر Report Size / Report Count آیتم ها تعیین می شود؛ به عنوان مثال، یک بانک از 8 سوئیچ روشن/خاموش می تواند در 1-بایت Report شده توسط یک Input item متغیر که در آن هر بیت نشان دهنده وضعیت یک سوئیچ هستش ( اندازه گزارش = 1، تعداد گزارش = 8 )؛ در عوض، یک آیتم ورودی متغیر می تواند 1-بایت گزارش مورد استفاده برای نشان دادن حالت از چهار دکمه سه قسمت، که در آن حالت هر دکمه با دو بیت ( اندازه گزارش = 2، تعداد گزارش = 4) اضافه شده است؛ یا 1 بایت از یک متغیر ورودی متغیر می تواند موقعیت x یک جوی استیک را نشان دهد ( اندازه گزارش = 8، تعداد گزارش = 1 ).

یک آرایه یک ابزار جایگزین برای توصیف داده ها از گروهی از دکمه ها را فراهم می کند؛ آرایه ها کارآمدتر هستند اگرچه انطاف پذیری کمتری دارند نسبت به متغییر ها؛ به جای بازگشت یک بیت برای هر دکمه در گروه، یک آرایه یک index را در هر فیلد که مطابق با دکمه فشرده است ارسال میکند (مثل کد های صفحه اسکن)؛ مقدار خارج از محدوده و فیلد آرایه هیچ کنترلی در نظر گرفته نمی شود؛ دکمه ها یا کلید های موجود در یک آرایه که به طور همزمان فشرده می شوند، باید در چندین قسمت گزارش شوند؛ بنابراین، تعداد فیلدها در یک آیتم ورودی آرایه ( گزارش تعداد ) حداکثر تعداد کنترل های همزمان را می توان گزارش کرد؛ یک صفحه کلید می تواند تا سه کلید همزمان با استفاده از آرایه با سه فیلد 8 بیت گزارش دهد ( گزارش اندازه = 8، تعداد گزارش = 3 )؛ Logical Minimum مقدار پایین ترین مقدار index بازگشت شده توسط آرایه را مشخص می کند و Logical Maximum بزرگترین را مشخص می کند؛ تعداد عناصر در آرایه می تواند با بررسی تفاوت بین Logical Minimum و Logical Maximum استنتاج شود ( تعداد عناصر = Logical Maximum - Logical Minimum + 1 )

چیزی که من فهمیدم : پس نوع داده آرایه اینطور هستش که مثلا 8 تا کلید داریم، فلذا Logical Minimum = 1 و Logical Maximum = 8 هستش، هر کدوم از کلید ها که فشرده بشه، میاد و index ( موضعیت اون کلید ) رو ارسال میکنه، که همونطور که قبلا دیدید میشه تا 4 بایت تعریف کرد، فلذا میشه 4 کلید فشرده شده به صورت همزمان رو در آن واحد دیتاشو ارسال کرد ( چون فیلد bSize تعداد بایت های دیتا رو تعیین میکرد، به کمکش میشد حداکثر 4 بایت داده تعریف کرد، ولی دیتاشیت گفته حداکثر 3 کلید برا کیبرود - چرا؟ )

بیت دو، (Absolute(0) | Relative(1 : نشان می دهد که آیا داده ها مطلق/Absolute هستند ( براساس یک مبنای ثابت ) یا نسبی/Relative ( نشان دهنده تغییر در مقدار از آخرین گزارش )؛ دستگاه های نسبی/Relative مثل موس، میان تغییرات رو ارسال میکنند، مثلا موس 2 واحد به چپ و 3 واحد به بالا رفت ( حرکت موس در جهت های X و Y از نوع Relative و کلید های چپ/راست/وسط موس از نوع Absolute هستند )، ولی دستگاه های مطلق/Absolute مثل تبلت، میان مختصات دقیق رو ارسال میکنند، چون در هر لحظه مکان انگشت مبارک کاربر ^_^ ممکنه هر جایی از صفحه نمایش باشه.

بیت سه، (NoWrap(0) | Wrap(1 : نشان می دهد که آیا داده ها "رول بیش از" هنگامی که رسیدن به شدت بالا و یا کم ارزش. به عنوان مثال، یک شماره گیری که می تواند به صورت آزاد 360 درجه چرخش یابد، ممکن است مقادیر خروجی از 0 تا 10 را نشان دهد. اگر Wrap مشخص شود، مقدار بعد گزارش شده پس از گذشت 10 موقعیت در جهت افزایش، 0 خواهد بود. ( چیزی که من فهمیدم اینه که وقتی به مقدار حداکثرش برسه 0 میشه و وقتی از 0 اون ور تر بشه به مقدار حداکثرش میرسه، فک کنم )

بیت چهار، (Linear(0) | Nonlinear(1 : نشان می دهد که آیا داده خام از دستگاه به نحوی پردازش شده است و دیگر نشان دهنده یک رابطه خطی بین آنچه که اندازه گیری شده و داده های گزارش شده است. منحنی های شتاب و مناطق مرده joystick ( وقتی در حالت بدون حرکت و در وسط قرار داره، اون وضعیت میگن منطقه مرده ) نمونه هایی از این نوع داده ها هستند. تنظیمات حساسیت بر روی مورد یونیت ها تاثیر می گذارد، اما داده ها همچنان خطی هستند ( چیزی که من فهمیدم : مثلا مقدار یک joystick خطی هستش، در حالت وسط قرار داره، وقتی میبریش چپ یا راست مثلا، مقدارش کم کم زیاد میشه، ولی مثلا کلید های قطع و وصل، خطی نیستند - نمیدونم فک کنم اشتباه فهمیدم )

بیت پنج، (Preferred(0) | NoPreferred(1 : نشان می دهد که آیا کنترل دارای حالت ترجیحی است که به آن بازگشت می کند زمانی که کاربر فیزیکی با کنترل ارتباط برقرار نمی کند؛ Push button ها ( به غیر از toggle button ها ) و joystick های خودمرکزی ( یه سری جوی استیک ها هستند که به وضعیت اولیه برنمیگردن که کاربرهای خاص خودشونو دارند ولی این چیزی که تو دسته های بازی میبینید، به حالت اولیه بر میگردن که بهشون میگن خودمرکزی ) نمونه هایی از این دست هستند. ( چیزی که فهمیدم : دستگاه هایی که کاربر ولشون میکنه، مقدار اولیشون برمیگردن )

بیت شش، (NoNullPosition (0) | Null(1 : نشان می دهد که آیا کنترل دارای یک حالت است که در آن داده های معنی دار ارسال نمی شود. یکی از امکان استفاده از حالت خالی برای کنترلهایی است که نیاز به کاربر برای ارتباط فیزیکی با کنترل دارد تا بتواند اطلاعات مفیدی را گزارش دهد. به عنوان مثال، برخی از جویاستیک ها یک سوئیچ چند جهته ( hat switch ) دارند. وقتی سوئیچ کلاه فشرده نمی شود، در حالت خالی است. هنگامی که در یک حالت خالی، کنترل یک مقدار را در خارج از حداقل حداقل منطقی و حداکثر منطقی (بیشترین مقدار منفی مانند -128 برای مقدار 8 بیتی) گزارش می دهد.

بیت هفت، (Nonvolatile(0) | Volatile(1 : نشان می دهد که آیا مقدار کنترلی Feature یا Output باید توسط میزبان تغییر کند یا نه. خروجی بی ثبات می تواند با یا بدون تعامل میزبان تغییر کند. برای جلوگیری از مشکلات هماهنگ سازی، کنترل های فرار باید هر زمان ممکن باشد نسبی باشند. اگر خروجی بی ثباتی مطلق باشد، در هنگام صدور یک گزارش تنظیم (خروجی)، مقدار هر کنترلی را که نمی خواهید به یک مقدار در خارج از حداقل حداقل منطقی و حداکثر منطقی (بیشترین مقدار منفی، مانند - 128 برای مقدار 8 بیتی). خروجی نامعتبر برای یک کنترل توسط دستگاه نادیده گرفته می شود. ( این بیت برای input item ها تعریف نشده و رزرو شده هستش )

بیت هشت، (BitField(0) | BufferedBytes(1 : نشان می دهد که کنترل جریان یک بایت ثابت را منتشر می کند؛ محتویات فیلد داده توسط برنامه تعیین می شود. محتویات بافر به عنوان یک عدد کمی تفسیر می شود؛ داده های گزارش شده توسط یک آیتم Buffered Bytes باید در یک مرز 8 بیتی هم تراز شود؛ به عنوان مثال، داده های یک barcode reader.

بیت 9 تا 31 : رزرو شده اند.

ملاحظات : 

  1. اگر Input item از نوع array باشد، تنها ویژگی های Data/Constant و Variable/Array و Absolute/Relative اعمال میشود. ( چرا؟ )
  2. تعداد فیلدهای دیتا در یک item میتونه با بررسی مقادیر Report Size و Report Count تعیین بشه؛ برای مثال یک آیتم با Report Size = 8 و Report Count = 3 دارای 3 فیلد داده 8-بیتی هستش.
  3. مقدار بازگشت داده شده توسط یک Array item یک index است ( یعنی چی که یه index است؟ یه آرایه حاوی مثلا 8 بیت دیتا مگه نمیفرسته؟ )، بنابراین پیشنهاد میشه که :
    3.1) یک فیلد آرایه، مقدار 0 برگشت بده وقتی هیچ کنترلی در آرایه رخ نداده است.
    3.2) Logical Minimum = 1
    3.3) Logical Maximum برابر تعداد عناصر در آرایه هستش.
  4. Input item ها از طریق Control pipe با دستور (Get_Report(Input در دسترس هستند. ( چرا از طریق Control pipe ؟ فقط دستورات کنترلی میتونن از Control pipe استفاده کنن که - قاطی کردم )
  5. Report های نوع Input همچنین مقدار polling rate رو از طریق Interrupt In pipe ارسال میکنند.
  6. The Data|Constant, Variable|Array, Absolute|Relative, Nonlinear, Wrap, and Null State data for an Output item are identical to those data for an Input item.
  7. Output item ها Output report ها رو ایجاد میکنند که از طریق Control pipe با دستور (Set_Report(Output قابل دسترس هستند ( چرا از طریق Control pipe ؟ فقط دستورات کنترلی میتونن از Control pipe استفاده کنن که - قاطی کردم )
  8. Report های نوع Output میتونن به صورت اختیاری ارسال بشوند توسط Interrupt Out pipe.
  9. در حالی که عملکرد یکسان هستد، Item های Output و Feature در موارد زیر با همدیگه متفاوت هستند :
    9.1) item های Feature تنظیمات configuration تعریف میکنند برای دستگاه و معمولا توسط کنترل-پنل برنامه تنظیم میشوند؛ از آنجا که آنها رفتار یک دستگاه را تحت تاثیر قرار می دهند ( برای مثال button repeat rate, reset origin و ... )؛ Feature item ها معمولا برای برنامه های کاربردی سخت افزار قابل مشاهده نیستند؛ درعوض Output item ها قابل مشاهده هستند ( برای مثال LEDs, audio, tactile feedback و... )؛ سخت افزار برنامه کاربردی هم احتمالا Output item ها رو تغییر میده.
    9.2) Feature items may be attributes of other items. For example, an Origin Reset Feature may apply to one or more position Input items. Like Output items, Feature items make up Feature Reports accessible via the Control pipe with the Get_Report (Feature) and Set_Report (Feature) requests.

 

Collection/End Collection Item tag

یک Collection item ارتباط بین 2 یا چند داده رو شناسایی میکنه ( INPUT/OUTPUT/FEATURE )؛ برای مثال یک موس را میتوان به عنوان یه مجموعه 2 تا 4 داده در نظر گرفت ( x, y, button1, button2 )؛ در حالی که Collection item مجموعه ای از item ها رو باز میکنه، End Collection مجموعه ای از item ها رو میبنده.

خب بریم سراغ توضیح کامل هر یک از انواع collection :

Physical : یک physical collection برای مجموعه ای از item های داده که نقاط داده در یک نقطه هندسی جمع آوری شده را نشان می دهند، استفاده می شود؛ این برای دستگاههای حساس مفید است که ممکن است نیاز به ارتباط مجموعه داده های اندازه گیری شده یا حساس با یک نقطه واحد داشته باشد؛ این نشان نمیدهد که مجموعه ای از مقادیر داده ها از یک دستگاه مانند یک keyboard بیرون می آید؛ در مورد دستگاهی که موقعیت چندین سنسورهای را گزارش می کند، physical collection ها برای نشان دادن اینکه چه اطلاعاتی از هر یک از سنسورهای جداگانه به دست می آید استفاده می شود.

Application : گروهی از Main item که ممکن است برای برنامه های کاربردی آشنا باشند؛ همچنین می تواند مورد استفاده قرار گیرد برای شناسایی گروه های item با اهداف مختلف در یک دستگاه واحد؛ مثالهای معمول یک keyboard یا mouse هستند؛ یک keyboard با یک دستگاه integrated pointing می تواند به عنوان دو مجموعه کاربردی متفاوت تعریف شود؛ report های داده معمولا ( اما نه لزوما ) با مجموعه برنامه ها ( حداقل یک report ID در هر برنامه ) مرتبط است.

Logical : مجموعه ی logical زمانی استفاده می شود که مجموعه ای از item های داده یک ساختار داده کامپوزیت ایجاد کنند؛ یک مثال از این ارتباط بین یک بافر داده و یک شمارۀ بایت داده است؛ collection ارتباط بین شمارنده و بافر را ایجاد می کند.

Report : یک logical collection را تعریف می کند که تمام فیلدها در یک report رو بسته بندی می کنه ( پوشش میده، پنهان میکنه )؛ یک report ID منحصربفرد در این collection موجو است؛ یک برنامه به راحتی می تواند تعیین کند که آیا دستگاه از یک عملکرد خاص پشتیبانی می کند؛ توجه داشته باشید که هر مقدار Report ID معتبر می تواند برای Report collection اعلام شود.

Named Array : یک named array یک logical collection هستش که شامل یک آرایه از selector usage ها است؛ برای یک تابع مشخص شده، مجموعه ای از انتخابگرهای مورد استفاده توسط دستگاه های مشابه ممکن است متفاوت باشد. نامگذاری فیلدها معمولا در هنگام ثبت احوال سخت افزاری معمول است. برای تعیین اینکه آیا یک دستگاه از یک تابع خاص مانند وضعیت پشتیبانی می کند، یک برنامه ممکن است برای انتخاب چند حالت شناخته شده کاربردهای پیش از آن می توانند تعیین کنند که آیا دستگاه پشتیبانی شده است. استفاده از Array نامی اجازه می دهد تا فیلد آرایه ای که حاوی انتخابگرهای نامیده می شود، به این ترتیب تنها نیاز به درخواست برای استفاده از وضعیت برای تعیین اینکه دستگاه از اطلاعات وضعیت پشتیبانی می کند.

Usage Switch : سوئیچ استفاده یک مجموعه منطقی است که معنای کاربردهای آن را تغییر می دهد. این نوع مجموعه به برنامه کاربردی نشان می دهد که کاربردهای موجود در این مجموعه بایستی ویژه باشد. به عنوان مثال، به جای اعلان استفاده در صفحه LED برای هر عملکرد ممکن، استفاده از شاخص به مجموعه سوئیچ استفاده می شود و استفاده های استاندارد که در آن مجموعه تعریف شده است، اکنون می تواند به عنوان شاخص برای یک تابع به جای تابع خود شناخته شود . توجه داشته باشید که این نوع مجموعه برای مجموعه نشانه ها استفاده نشده است، برای این نوع مجموعه منطقی استفاده می شود.

Usage Modifier : معنای استفاده شده مربوط به مجموعه فراگیر اصلاح می شود. استفاده معمولی یک حالت عملیات واحد را برای یک کنترل تعریف می کند. اصلاح کننده استفاده می کند تا حالت عملیاتی یک کنترل را گسترش دهد. به عنوان مثال، یک LED به طور معمول روشن یا خاموش است. برای حالت های خاص دستگاه ممکن است یک روش عمومی از چشمک زدن یا انتخاب رنگ یک LED استاندارد داشته باشد. پیوستن استفاده از LED به یک مجموعه تغییر دهنده کاربرد، به یک برنامه کاربردی نشان می دهد که استفاده از یک حالت عملیاتی جدید را پشتیبانی می کند.

ملاحظات :

  • All Main items between the Collection item and the End Collection item are included in the collection. Collections may contain other nested collections.
  • Collection items do not generate data. However, a Usage item tag must be associated with any collection (such as a mouse or throttle). Collection items may be nested, and they are always optional, except for the top-level application collection.
  • If an unknown Vendor-defined collection type is encountered, then an application must ignore all main items declared in that collection. Note that global items declared in that collection will effect the state table.
  • If an unknown usage is attached to a known collection type then the contents of that collection should be ignored. Note that global items declared in that collection will effect the state table.
  • String and Physical indices, as well as delimiters may be associated with collections.
2.2) Global Items

2.2) Global Items

Global items describe rather than define data from a control.
A new Main item assumes the characteristics of the item state table.
Global items can change the state table.
As a result Global item tags apply to all subsequently defined items unless overridden by another Global item.

Global Items

Usage Page : یک عدد صحیح بدون علامت ( Unsigned integer ) که Usage Page فعلی رو مشخص میکنه؛ از اونجایی که usage مقدارش 32بیتی هستش، Usage Page item ها می تواند برای ذخیره فضای در یک report descriptor با تنظیم 16 بیت پر ارزش از کاربردهای بعدی استفاده شود؛ هر usage که به دنبال آن است که 16 بیت یا کمتر تعریف می شود، به عنوان یک Usage ID شناسایی می شود و با Usage Page برای استفاده از 32 بیتی مرتبط می شود. ( بررسی ترجمه )

 

Logical Minimum : حداقل مقدار logical unit ها؛ این حداقل مقداری هستش که item ها ( از نوع variable یا array ) گزارش ( report ) خواهند کرد؛ برای مثال، یک موس، مقدار موقیت X اش بین 0 تا 128 هستش، فلذا Logical Minimum برابر 0 و Logical Maximum برابر 128 خواهد بود.

Logical Maximum : حداکثر مقدار logical unit ها؛ این حداکثر مقداری هستش که item ها ( از نوع variable یا array ) گزارش ( report ) خواهند کرد.

 

Physical Minimum : حداقل مقدار برای physical extent یک item ( از نوع variable ). این نشان دهنده Logical Minimum با unitها است که به آن اعمال می شود.

Physical Maximum : حداکثر مقدار برای physical extent یک item ( از نوع variable ).

 

سوال : فرق بین Logical Minimum/Logical Maximum و Physical Minimum/Physical Maximum و Usage Minimum/Usage Maximum چیه؟ قاطی کردم.

 

Unit Exponent : مقدار unit exponent بر مبنای 10 هستش ( توضیح بیشتر در قسمت "ملاحظات - مورد 1" )

 

Unit : مقدار Unit ( توضیح بیشتر در قسمت "ملاحظات - مورد 1" )

 

Report Size : یه عدد صحص مثبت برا تعیین تعداد بیت فیلدهای report؛ که این اجازه رو به تجزیه کننده میده که یک item map برای استفاده report handler ایجاد کنه، برای مطالعه بیشتر به بخش Report Protocol مراجعه کنید.

Report Count : یه عدد صحص مثبت برا تعین تعدا فیلد داده item مد نظر ( با اندازه تعیین شده توسط Report Size )

توجه : درباره Report Size و Report Count پیشتر در قسمت "Report Descriptor" توضیح دادم.

 

Report ID : یه عدد صحیح مثبت که Report ID رو مشخص میکنه؛ اگر Report ID tag در هرجایی از Report descriptor استفاده شود، تمام data report ها برای دستگاه پردازش میشوند توسط یک فیلد با نام ID که 1-بایت هستش؛

All items succeeding the first Report ID tag but preceding a second Report ID tag are included in a report prefixed by a 1-byte ID.
All items succeeding the second but preceding a third Report ID tag are included in a second report prefixed by a second ID, and so on.

این مقدار Report ID نشان دهنده پیشوند اضافه شده به یک report خاص است؛ برای مثال، یک Report descriptor میتواند یک report با سه بایت دیتا و یک بایت Report ID ( با مقدار 1 ) را تعریف کند؛ فلذا دستگاه در هر report داده، 4 بایت را تولید می کند که اولین بایتش 1 است؛ این دستگاه همچنین ممکن است report های دیگری را تولید کند، هر کدام با یک ID منحصر به فرد؛ که این اجازه رو به میزبان میده تا report های مختلف ( یی که از یک interrupt in pipe میاد ) رو از همدیگه شناسایی کنه؛ همچین این اجازه رو به دستگاه میده تا report های مختلف ( یی که از یک interrupt out pipe میاد ) رو از همدیگه شناسایی کنه؛ Report ID با مقدار 0 رزرو شده هستش و نباید استفاده بشه.

Push : Places a copy of the global item state table on the stack

Pop : Replaces the item state table with the top structure from the stack

 

ملاحظات : 

1) در حالی که Logical Minimum و Logical Maximum مقادیری را که توسط یک دستگاه نشان داده می شوند محدود می کنند، Physical Minimum و Physical Maximum به معنی این محدودیت ها اجازه می دهد که مقادیر گزارش را مقدور کنیم؛ به عنوان مثال، یک دماسنج می تواند مقادیر منطقی 0 و 999 داشته باشد، اما دامنه های فیزیکی 32 و 212 درجه است؛ با الگوریتم زیر resolution رو میشه تعیین کرد :

هنگام تجزیه و تحلیل خطی یک report descriptor، مقدار global state از Unit Exponent و Physical Minimum و Physical Maximum در حالت "UNDEFINED" در نظر گرفته می شوند تا زمانی که اعلام شوند. ( خب این جمله توی دیتاشیت با کد بالا در تعارض هستش که )

برای مثال، یک موس 400dpi میتونه item هایی با مقادیر شبیه جدول زیر داشته باشه :

توجه : Dots per inch = dpi ( یعنی 400 نقطه در هر اینچ )؛ 1inch=2.54cm=2540mm؛ فلذا میشه 400 نقطه در هر 2540mm که میشه 1 نقطه در هر 6.35mm ( حالا پیکسل میاد وسط، پیکسل هم اندازه های مختلفی داره!؛ بعد فرق این دو، PPI vs DPI و .... خودش یه مطلب میشه، نه من حوصله مطالعه دارم و نه اینجا جاشه، بخیال، خخخ )

400-dpi mouse

بنابراین، محاسبه resolution طبق فرمول گفته شده به صورت زیر میشه :

Resolution = (127-(-127)) / ((3175-(-3175)) * 10^(-4)) = 4 * 10^(-6) = 400 counts per inch

2) Unit item مقادیری مطابق جدول زیر میگیرد ( جدول زیر رو نفهمیدم، در مثال بالا جدول زیر چطور میشه؟ ) :

Unit item qualifies

3) تا زمانی که Physical Minimum و Physical Maximum در report descriptor تعریف نشده اند و یا مقدار هردوشون 0 هستش، به ترتیب برابر با Logical Minimum و Logical Maximum فرض میشوند.

4) Codes and exponents not shown in the preceding table :

Codes and exponents

5) اکثر واحدهای پیچیده را می توان از واحد های پایه طول، جرم، زمان، دما، شدت جاری و نور در نظر گرفت؛ به عنوان مثال انرژی ( بر حسب ژول ) می تواند به صورت زیر نشان داده شود :

joule = [mass(grams)][length(centimeters)^2 ][time(seconds)^(-2)]

توجه : هرچی بررسی کردم و میکنم به این نتیجه میرسم که فرمول بالا اشتاه هستش و باید در 10000 ضرب بشه.

تگ Unit exponent برابر 7 خواهد بود ( چرا؟ 7 از کجا اومده؟ ) زیرا یک ژول از کیلوگرم ( 1 کیلوگرم برابر 1000 گرم ) و متر تشکل شده؛ به عنوان مثال، موارد زیر را در نظر بگیرید :

6) تعدادی از رایج ترین unit ها در جدول زیر نشان داده شده ( توضیح بیشتر - نفهمیدم - نحوه استفاده از جدول زیر؟ ) :

7) In the case of an array, Report Count determines the maximum number of controls that may be included in the report and consequently the number of keys or buttons that may simultaneously be pressed as well as the size of each element. For example, an array supporting up to three simultaneous key presses, where each field is 1 byte, would look like this:

...
Report Size (8),
Report Count(3),
...

In the case of a variable item, the Report Count specifies how many controls are included in the report. For example, eight buttons could look like this :

...
Report Size (1),
Report Count (8),
...

8) اگر از Report ID ها قرار باشه استفاده بشه، اونوقت Report ID باید پیش از اولین Input/Output/Feature main item در یک report descriptor تعریف شود.

9) The same Report ID value can be encountered more than once in a report descriptor. Subsequently declared Input, Output, or Feature main items will be found in the respective ID/Type (Input, Output, or Feature) report.

2.3) Local Items

2.3) Local Items

Local item tag ها ویژگیهای کنترل را مشخص میکنند؛ این item ها به Main item بعدی منتقل نمی شوند(یعنی چی؟)؛ اگر یک Main item بیش از یک کنترل را تعریف کند، ممکن است چندین Local item tag مشابه پیش رو داشته باشد(نفهمیدم)؛ به عنوان مثال، یک Input item ممکن است چندین Usage tag را با آن داشته باشد، یکی برای هر کنترل.

Local Items

Usage : خب Usage index برای یک item usage، نشان دهنده یک usage پیشنهاد شده برای item یا collection است؛ در موردی که یک item نشان دهنده کنترل های چندگانه است، یک Usage tag می تواند یک usage را برای هر متغیر یا عنصر در یک آرایه پیشنهاد دهد.

 

Usage Minimum : تعریف میکند که usage با array یا bitmap شروع میشود ( بررسی ترجمه )

Usage Maximum : تعریف میکند که usage با array یا bitmap تمام میشود ( بررسی ترجمه )

 

Designator Index : قسمت بدنه مورد استفاده برای کنترل را تعیین می کند؛ Index اشاره به یک designator در Physical descriptor دارد.

 

Designator Minimum : شاخص نماد شروع را با یک آرایه یا بیت مپ تعریف می کند ( بررسی ترجمه )

Designator Maximum : شاخص نماد پایان را با یک آرایه یا بیت مپ تعریف می کند ( بررسی ترجمه )

 

String Index : خب String index برای یک String descriptor، اجازه میده که یک string با یک item یا کنترل خاص مرتبط بشه.

 

String Minimum : اولین string index هنگام اختصاص یک گروه از string های متوالی به کنترل در array یا bitmap را مشخص می کند.

String Maximum : آخرین string index هنگام اختصاص یک گروه از string های متوالی به کنترل در array یا bitmap را مشخص می کند.

 

Delimiter : شروع یا پایان یک مجموعه از local item ها رو تعیین میکنه ( 1=مجموعه باز، 0=مجموعه بسته )

 

ملاحظات : 

1) در حالی که Local item ها به Main item بعدی منتقل نمی شوند، ممکن است به بیش از یک کنترل در یک item واحد اعمال شوند؛ به عنوان مثال اگر یک Input item که پنج کنترل را تعریف می کند قبل از سه Usage tag، سه usage به ترتیب به سه کنترل اول اختصاص داده می شوند و usage سوم نیز به کنترل های چهارم و پنجم اختصاص داده می شود؛ اگر یک item هیچ کنترل ندارد ( Report Count = 0 )، اون وقت Local item tag ها به Main item ( معمولا یک مجموعه آیتم ) اعمال می شود. ( نفهیمدم )

2) برای اختصاص دادن usage های منحصر به فرد به هر کنترل در یک Main item یکتا/تنها، به سادگی هر Usage tag را به طور متوالی ( یا از استفاده Usage Minimum یا Usage Maximum ) مشخص کنید. ( نفهیمدم )

3) All Local items are unsigned integers.

Note : It is important that Usage be used properly. While very specific usages exist (landing gear, bicycle wheel, and so on) those usages are intended to identify devices that have very specific applications. A joystick with generic buttons should never assign an application-specific usage to any button. Instead, it should assign a generic usage such as “Button.” However, an exercise bicycle or the cockpit of a flight simulator may want to narrowly define the function of each of its data sources.

4) It is also important to remember that Usage items convey information about the intended use for the data and may not correspond to what is actually being measured. For example, a joystick would have an X and Y Usage associated with its axis data (and not Usages Rx and Ry.)

5) Because button bitmaps and arrays can represent multiple buttons or switches with a single item, it may be useful to assign multiple usages to a Main item. Usage Minimum specifies the usage to be associated with the first unassociated control in the array or bitmap. Usage Maximum specifies the end of the range of usage values to be associated with item elements. The following example illustrates how this could be used for a 105-key keyboard.

6) If a Usage Minimum is declared as and extended usage then the associated Usage Maximum must also be declared as an extended usage.

7) Interpretation of Usage, Usage Minimum or Usage Maximum items vary as a function of the item’s bSize field. If the bSize field = 3 then the item is interpreted as a 32 bit unsigned value where the high order 16 bits defines the Usage Page and the low order 16 bits defines the Usage ID. 32 bit usage items that define both the Usage Page and Usage ID are often referred to as “Extended” Usages.

If the bSize field = 1 or 2 then the Usage is interpreted as an unsigned value that selects a Usage ID on the currently defined Usage Page. When the parser encounters a main item it concatenates the last declared Usage Page with a Usage to form a complete usage value. Extended usages can be used to override the currently defined Usage Page for individual usages.

8) دو یا چند usageهای جایگزین ممکن است با کنترل به راحتی آنها را با آیتم های Delimiter مرتبط کنند؛ Delimiters اجازه می دهد تا aliases برای یک کنترل تعریف شود تا برنامه بتواند به آن بیش از یک راه دسترسی پیدا کند؛ کاربردهای که مجموعه ای از محدودیت ها را تشکیل می دهند، به ترتیب اولویت بندی می شوند، جایی که اولین استفاده شده، مورد استفاده ترین مورد برای کنترل است.

تجزیه کننده های HID باید Delimiter ها را اداره کنند، اما پشتیبانی از usage های جایگزین که آنها تعریف می کند اختیاری است؛ Usage های غیر از اولین (بیشترین ترجیح) استفاده تعریف شده ممکن است توسط نرم افزار سیستم قابل دسترس نباشد. ( کلا نفهمیدم )

9) Delimiter را نمیتوان در هنگام تعریف usage های مورد استفاده در مورد Application Collection ها یا Array item ها استفاده کرد. ( نفهمیدم )

 

Padding

Reports can be padded to byte-align fields by declaring the appropriately sized main item and not declaring a usage for the main item.

3) Physical Descriptors ( این قسمت هنوز مورد نیازم نشده و بررسی نکردم صحت محتواشو )

3) Physical Descriptors

این فصل رو کلا نفهمیدم ( ترجمش هم بررسی بشه )

یک Physical Descriptor، ساختار داده ای است که اطلاعات مربوط به قسمت خاص یا قسمت های بدن انسان را فراهم می کند که کنترل یا کنترل را فعال می کنند؛ برای مثال، یک physical descriptor ممکن است نشان دهد که انگشت دست راست برای فعال کردن دکمه 5 استفاده می شود؛ یک برنامه می تواند از این اطلاعات برای اعمال قابلیت ها به کنترل های یک دستگاه استفاده کند.

توجه : Physical Descriptor ها کاملا اختیاری هستند؛ آنها پیچیدگی را اضافه می کنند و در مقایسه با اکثر دستگاه ها بسیار کم هستند؛ با این حال، بعضی از دستگاهها، مخصوصا کسانی که دارای تعداد زیادی کنترل مشابه هستند (به عنوان مثال، دکمه ها)، نشان می دهد که Physical Descriptor ها به برنامه های مختلف کمک می کند تا عملکرد این کنترل ها را به صورت سازگار تر تعیین کند؛ اگر برنامه ای برای حمایت از Physical Descriptor ندارید، از خوندن این قسمت خودکاری کنید.

توصیفگرهای مشابه فیزیکی به مجموعه ها تقسیم می شوند. عناصر فهرست نماد موجود در آیتم نقشه توصیفگر گزارش (یا کنترل) به یک توصیفگر فیزیکی خاص موجود در یک مجموعه توصیفگر فیزیکی (که در اینجا به طور عمومی به عنوان یک مجموعه توصیفگر اشاره شده است).

هر مجموعه توصیفی شامل یک سرصفحه کوتاه و به دنبال آن یک یا چند توصیف فیزیکی است. سرصفحه تعریف تعریف (اینکه آیا مجموعه توصیفگر در یک کاربر راست یا چپ هدف قرار می گیرد) و ترجیح مجموعه را تعریف می کند. برای یک بروز خاص، یک فروشنده میتواند توصیفگرهای متناوب فیزیکی را تعریف کند (برای مثال، یک کاربر راست دست ممکن است بتواند یک دستگاه را در بیش از یک راه نگه دارد، بنابراین انگشتان دست خود را که آیتم های منحصر به فرد را لمس می کنند، ترسیم می کنند).

هر Physical Descriptor شامیل 3 فیلد زیر هستش :

  • Designator : قسمت واقعی بدن را مشخص می کند که یک مورد را به اثبات می رساند، مثلا دست.
  • Qualifier : بیشتر نشانگر را تعریف می کند، مثلا دست راست یا چپ.
  • Effort : ارزش quantifying تلاش کاربر باید برای اعمال مورد استفاده است.

اگر عناصر چندگانه همان ترکیب Designator / Qualifier را شناسایی کنند، می توان از مقدار تلاش برای حل تخصیص توابع استفاده کرد. یک مقدار تلاش از 0 برای تعریف دکمه یک انگشت بر روی زمانی که دست در موقعیت "در حالت استراحت" است، استفاده می شود، یعنی عملا هیچ تلاشی برای کاربر برای فعال کردن دکمه لازم نیست. مقدار تلاش افزایش می یابد به عنوان انگشت به کشش برای رسیدن به یک کنترل است.

تنها زمانی که دو یا چند کنترل دارای ترکیبات Designator / Qualifier / Effort هستند، این است که آنها به صورت فیزیکی متصل هستند. یک کلاه کلیدی کوتاه با "+" در یک طرف و "-" در طرف دیگر نمونه خوبی از این است. اگر به صورت دو دکمه ی جداگانه به صورت الکتریکی اجرا شود، ممکن است هر دو در همان زمان فشار داده شوند، هرچند که هر دو زیر کلاه کلیدی هستند. اگر فروشنده تصمیم گرفت که برای این محصول، با فشار دادن دکمه های "+" و "-" به طور همزمان معتبر باشد، آنها را به عنوان دو دکمه دیسک مجزا با یکسان توصیفگرهای فیزیکی توصیف خواهند کرد. با این حال، اگر کلاه کلیدی با برچسب "Volume" و با فشار دادن هر دو دکمه در همان زمان معنی نداشت، یک فروشنده احتمالا گزینه ای برای توصیف دکمه ها به عنوان یک آیتم با سه حالت معتبر: خاموش، حجم بیشتر (+)، و حجم کم (-). در این مورد تنها یک توصیفگر فیزیکی مورد نیاز است.

یک جوی استیک که دارای دو دکمه (A و B) در سمت چپ پایه و دکمه ی ماشه ای در جلوی چوب است که منطقا با دکمه A است، در نظر بگیرید. پایه جوی استیک اغلب در سمت چپ در حالی که چوب با حق دستکاری می شود. بنابراین، اولین مجموعه توصیف کننده دکمه A را به عنوان :

Index Finger, Right, Effort 0

به طور مشابه، دکمه B به عنوان :

Thumb, Left, Effort 0

اگر جوی استیک بر روی میز قرار داده شد و دست چپ برای کنترل هر دو دکمه در پایه استفاده شد، سپس یک مجموعه توصیفگر می تواند یک نقشه برداری متناوب برای دکمه A از:

Middle Finger, Left, Effort 0

دکمه B به عنوان:

Index Finger, Left, Effort 0

مهم : برچسب های نشانگر اختیاری هستند و ممکن است برای همه، بعضی یا هیچ یک از اقلام یا عناصر دستگاه ارائه نشوند.

مجموعه توصیفگر 0 یک مجموعه توصیفگر خاص است که تعداد مجموعه های توصیفگر اضافی را مشخص می کند و همچنین تعداد توصیفگرهای فیزیکی در هر مجموعه.

پس از دریافت درخواست Get_Descriptor از میزبان، یک دستگاه کلاس HID مجموعه توصیفگر را مشخص می کند که در درخواست request wValue کم بایت است. یک مجموعه توصیف کننده شامل یک هدر و یک یا چند توصیفگر فیزیکی است.

دستگاه کلاس HID از قالب زیر برای توصیفگر فیزیکی استفاده میکند.

 

ملاحظات :

1) فیلد Bias نشان می دهد که چه دسته ای از توصیف کننده را مشخص می کند. این ممکن است در برخی از دستگاهها اعمال نشود.

توجه : یک دستگاه که تنها در دست راست قرار می گیرد، مجموعه های توصیفگر را با تقاطع چپ دست باز نمی گرداند.

2) زمینه ترجیح نشان می دهد که آیا مجموعه توصیفگر شامل اطلاعات نامطلوب ترجیحی یا جایگزین است. فروشنده یک مقدار اولویت 0 را برای مجموعه ترجیحی یا معمول ترین اطلاعات فیزیکی تعریف می کند. مقادیر ترجیح بالاتر، مجموعه های توصیفگرای کمتر را نشان می دهد.

3) توصیفگرهای فیزیکی در یک مجموعه توصیفگر توسط عناصر Indexator Index در توصیفگر گزارش اشاره شده است.

4) یک توصیفگر فیزیکی دارای بخش های زیر است:

5) فیلد کلاسیک نشان می دهد که کدام دست (یا نیمی از بدن) مشخص کننده تعیین کننده است. این ممکن است برای برخی از دستگاهها اعمال نشود.

6) فیلد تلاش نشان می دهد که کاربر برای دسترسی به کنترل آسان است. مقدار 0 مشخص می کند که کاربر می تواند به سرعت و به راحتی کنترل کند. همانطور که ارزش افزایش می یابد، کاربر برای کنترل آن بیشتر دشوار می شود یا طول می کشد.

 

1) Request های استاندارد

Standard Requests

کلاس HID از درخواست استاندارد Get_Descriptor استفاده میکند ( که در دیتاشیت USB توضیح داده شده است )؛ وقتی دستور (Get_Descriptor(Configuration اجرا میشود ( که شماره پیکربندی رو هم ذکر میکنه - چون دستگاه میتونه چندین پیکربندی داشته باشه )، دستگاه میاد و اون Configuration descriptor، تمام Interface descriptor هاش، تمام Endpoint descriptor هاش و HID descriptor هر interface رو ارسال میکنه؛ دستگاه نباید String descriptor ها، HID Report descriptor ها و یا هر HID class descriptor اختیاری رو ارسال کنه؛ HID descriptor باید بین Interface descriptor و Endpoint descriptor قرار بگیره؛ مثال زیر رو ببینید :

 

این عکس رو ببینید چه چند تا نکته دربارش بگم ( مربوط به درخواست Get_Descriptor از دیتاشیت USB هستش ) :

توجه 1 : بایت کم ارزش فیلد wValue ( با نام Descriptor Index ) از درخواست Get_Descriptor، برای Physical Descriptor مشخص کننده شماره index مد نظر هستش ( چون چندین Physical Descriptor ممکنه وجود داشته باشه، در ضمن شمارش Physical Descriptor ها از 1 شروع میشه و اولین Physical Descriptor مقدار index = 1 دارد، ولی برا توضیح دهنده های استاندارد که از 0 شروع میشد؟ چرا؟ ) ولی برا Descriptor های دیگه کلاس HID، چون از هر کدوم حداکثر 1 دونه میتونیم داشته باشم، فلذا این بایت باید 0 باشد.

توجه 2 : فیلد wIndex، برای کلاس HID، مشخص کننده شماره HID Interface هستش ( برای string descriptor ها، این فیلد مشخص کننده Language ID هستش و برا descriptor های استاندارد دیگه، برابر 0 هستش )

3) Requesting Physical Descriptor set 0 returns a special descriptor identifying the number of descriptor sets and their sizes.

دو عکس زیر رو هم ببینید و این قسمت تمام :

HID Class Get_Descriptor Request

HID Class Set_Descriptor Request

2) Request های کلاس HID

HID Requests

در مطلب "آموزش پروتکل USB" در عنوان "فرمت فیلد DATA از پکیج DATA از ترنزکشن SETUP" عکس 2-9، چون این فرمت داده در مد کنترل ثابت هستش، اینجا هم از همون فرمت داده استفاده میکنیم.

فیلد bmRequestType : بیت 0 تا 4 باید روی interface تنظیم بشه و بیت 5 و 6 روی class تنظیم بشه ( مقدار دهی بشه ) و بیت 7؛ فلذا این فیلد برای HID Request ها، یکی از مقادیر 0b10100001 و یا 0b00100001 میتونه باشه ( اگه اگه توجه کنید این دو فقط در بیت 7 ام با هم فرق دارن که تعیین کننده جهت ارسال داده هستش، از میزبان به دستگاه یا برعکس )

فیلد bRequest : همونطور که میدونید، این فیلد مشخص کننده نوع درخواست هستش، که به صورت زیر مقدار دهی میشه :

HID bRequest

توجه 1 : تمام دستگاه ها باید درخواست Get_Report رو پشتیبانی کنند ( اجباری هستش )

توجه 2 : درخواست Get_Protocol و Set_Protocol تنها برای دستگاه هایی که از boot پشتیبانی میکنند، کاربرد دارد.

2.1) Get_Report Request

درخواست Get_Report این امکان رو به میزبان میده تا یک report رو از طریق Control pipe دریافت کند.

HID Get_Report Request

فیلد wValue ( دو بایت ) : در بایت پر ارزش مقدار Report Type و در بایت کم ارزش Report ID قرار دارد؛ Report ID باید 0 باشد اگر از Report ID ها استفاده نمیشود؛ مقدار Report Type به صورت زیر تنظیم میشه :

Report Type Value
Input 1
Output 2
Feature 3
Reserved 4 - 255

ملاحظات :

1) این درخواست در زمان راه اندازی اولیه برای absolute item ها و برای تعیین کردن وضعیت feature item ها مفید است؛ این درخواست در نظر گرفته نشده است که برای نظارت بر وضعیت دستگاه به طور منظم استفاده شود.

2) Interrupt In pipe باید برای تکرار Input report ها استفاده شود؛ پاسخ Input report دارای فرمت یکسانی با report ها از Interrupt pipe دارد ( بررسی ترجمه )

3) یک Interrupt Out pipe ممکن است به صورت اختیاری برای Output report ها با تاخیر زمانی کم ( low latency ) استفاده شود؛ Output report ها بر روی Interrupt Out pipe ها فرمت یکسانی دارند، این همانند output report ها هستش که بر روی Control pipe ارسال میشود؛ اگر یک Interrupt Out endpoint اعلام نشده باشد ( بررسی ترجمه )

2.2) Set_Report Request

درخواست Set_Report این امکان رو به میزبان میده تا یک report به دستگاه ارسال کند، احتمالا تنظیم وضعیت input/output/feature کنترل ها.

HID Set_Report Request

ملاحظات :

1) فیلد های درخواست Set_Report و Get_Report یکسان هستند ( به قول دیتاشت : معنای یکسانی دارند! )، با این حال بیت جهت داده در فیلد bmRequestType برا این دو درخواست معکوس همدیگه هستش ( که خب طبیعیه، Set_Report یه سری اطلاعات برا دستگاه میفرسته فلذا بیت جهتش باید 0 باشه و برا Get_Report چون دستگاه به میزبان اطلاعات میده، باید 1 باشه )

2) A device might choose to ignore input Set_Report requests as meaningless. Alternatively these reports could be used to reset the origin of a control (that is, current position should report zero). The effect of sent reports will also depend on whether the recipient controls are absolute or relative.

2.3) Get_Idle Request

درخواست Get_Idle مقدار فعلی نرخ بیکاری ( idle rate ) برای یک Input report خاص رو میخونه.

HID Get_Idle Request

توجه : برای توضیحات بیشتر به توضیحات ارائه شده در درخواست Set_Idle مراجعه کنید.

2.4) Set_Idle Request

درخواست Set_Idle یک report خاص در Interrupt In pipe رو بیصدا ( خاموش/در نظر نگرفتن ) میکنه تا زمانی که یه رویداد جدید رخ بده یا مقدار مشخصی از زمان بگذره.

HID SET_IDLE Request

این درخواست برای محدود کردن فرکانس report های ( تعداد گزارش در 1s ) یک interrupt in endpoint استفاده میشود؛ مخصوصا این درخواست باعث میشه که endpoint در پاسخ به هر poll یی NAK ارسال کنه در یک interrupt in endpoint تا زمانی که report فعلی تغییر نکرده؛ polling برای مدت زمان مشخص شده بر اساس NAK ادامه خواهد یافت؛ این درخواست دارای بخش های زیر هستش :

1) Duration : وقتی که بایت پر ارزش فیلد wValue، صفر هستش، مدت زمان نامحدود هستش؛ endpoint برای همیشه report را مهار میکند، تنها زمانی report رخ میدهد که یک تغییری در report data شناسایی شود.

زمانی که بایت پر ارزش فیلد wValue صفر نیست ( 1 تا 255 )، از یک زمان ثابت استفاده میشود؛ که زمان فوق از حاصل ضرب این بیت، در 4ms بدست می آید، فلذا زمان نهایی بین 4ms تا 1020ms خواهد بود؛ اگر مدت زمان کمتر از مقدار polling rate دستگاه باشد، report ها در polling rate تولید می شوند.

اگر زمان تعیین شده ( Duration ) سپری شود و تغییری در report data مشاهده نشود، اونوقت یک reprot تنها توسط endpoint تولید خواهد شد و report inhibition با استفاده از مدت زمان قبلی دوباره شروع میشود.

2) Report ID : اگر بایت کم ارزش فیلد wValue صفر باشد، آنگاه نرخ بیکاری ( idle rate ) در تمام input report های تولید شده توسط دستگاه اعمال میشود؛ وقتی که بایت کم ارزش فیلد wValue صفر نیست، اون وقت نرخ بیکاری ( idle rate ) تنها بر Report ID مشخص شده توسط بایت کم ارزش اعمال میشود ( یعنی چی؟ بایت کم ارزش که Duration رو تعیین میکنه، متوجه نشدم )

3) Accuracy ( دقت ) : این زمان تعیین شده ( duration ) باید دقت زیر رو داشته باشه :

±(10% + 2ms)

4) Latency ( تاخیر زمانی ) : یک درخواست جدید اجرا می شود همانطور که اگر بلافاصله پس از آخرین گزارش صادر شد، اگر درخواست جدید حداقل قبل از پایان دوره فعلی، 4 میلی ثانیه باشد، دریافت می شود؛ اگر درخواست جدید در ظرف 4 میلی ثانیه از پایان دوره فعلی دریافت شده باشد، درخواست جدید تا بعد از گزارش اثر نخواهد داشت.

اگر دوره فعلی از مدت زمان جدید تجویز شده گذشته باشد، یک گزارش بلافاصله تولید خواهد شد.

 

اگر interrupt in endpoint سرویس چندین report را داشته باشد، سپس درخواست Set_Idle می تواند برای تأثیر فقط بر میزان که در آن گزارش های تکراری برای شناسه Report مشخص شده تولید می شود، به عنوان مثال، یک دستگاه با دو report ورودی می تواند یک نرخ بیکاری 20ms برای گزارش ID 1 و 500ms برای گزارش ID 2 مشخص کند.

نرخ بیکاری پیشنهادی پیش فرض (سرعت زمانی که دستگاه راه اندازی می شود) 500ms برای keyboard ها (تاخیر قبل از اولین بار تکرار) و بی نهایت برای joysticks و mice.

2.5) Get_Protocol Request

درخواست Get_Protocol میاد بررسی میکنه که کدوم پروتکل در حال حاضر فعال هستش ( boot protocol یا report protocol )

HID GET_PROTOCOL Request

این درخواست توسط دستگاه ها در زیر کلاس boot پشتیبانی می شود؛ فیلد wValue تعیین می کند که کدام پروتکل باید استفاده شود.

2.6) Set_Protocol Request

به کمک درخواست Set_Protocol میتونیم بین boot protocol و report protocol جابجا بشیم ( سویچ کنیم )

HID Set_Protocol Request

این درخواست توسط دستگاه ها در زیر کلاس boot پشتیبانی می شود؛ فیلد wValue تعیین می کند که کدام پروتکل باید استفاده شود.

در راه اندازی اولیه، به صورت پیشفرض مقدار report protocol برای تمام دستگاه ها اعمال خواهد شد، با این حال میزبان نباید هیچ فرضیه ای درباره وضعیت دستگاه داشته و پروتکل دلخواه را هر زمان که یک دستگاه را راه اندازی می کند تنظیم کند.

 

 

Report Protocol ( فرمت داده ای که دستگاه ارسال میکند )

Report Types

Report ها حاوی داده از یک یا چند item هستند؛ transfer های داده از سمت دستگاه به میزبان از طریق Interrupt In pipe در قالب report ها ارسال میشود؛ Report ها همچنین ممکن است درخواست شوند ( polled ) و از طریق Control pipe و یا Interrupt Out pipe اختیاری ارسال شوند؛ یک report حاوی وضعیت تمام item های ( Input / Output / Feature ) متعلق به یک Report ID خاص هستش؛ نرم افزار کاربردی سخت افزار مسئولیت استخراج item های شخصی از report مبتنی بر Report descriptor رو بر عهده داره.

تمام مقادیر item ها در مرزهای بیتی بسته بندی میشود ( no byte or nibble alignment )؛ با این حال، item ها report میکنند مقادیر Null یا constant که ممکنه استفاده بشه برای مقادیر byte-align، یا Report Size ممکن است برای برخی از رشته ها بزرگتر از حد مورد نیاز باشد تا آنها را به یک مرز بایت گسترش دهیم.

طول بیت داده item ها از طریق Report descriptor بدست آمده است ( Report Size * Report Count )؛ داده های Item مرتب/منظم شده اند همانند مرتب شدن item ها در Report descriptor؛ اگر یک Report ID tag در Report descriptor استفاده شده بود، تمام report ها حاوی تک بایت ID پیشوند خواهند بود؛ اگر Report ID tag استفده نشده بود، تمام مقادیر در یک report تنها ارسال ( return ) میشوند و ID پیشوند در آن report وجود ندارد.

 

فرمت Report برای Item های استاندارد

فرمت report متشکل از 8-بیت شناسایی report و به دنبالش داده های متعلق به این report می باشد.

HID - Report Format for Standard Items

Report ID : فیلد Report ID هشت-بیت طول دارد؛ اگر هیچ Report ID tag یی در Report descriptor استفاده نشود، تنها فیلد Report وجود خواهد داشت و فیلد Report ID حذف خواهد شد.

Report Data : فیلد های داده طول متغییری دارند که وضعیت یک item را report میکنند.

 

فرمت Report برای Array Item ها

هر دکمه در یک آرایه یک شماره اختصاصی به نام یک index آرایه گزارش می دهد؛ این میتواند تفسیر شود داخل یک keycode با مراجعه به Usage Page و Usage عناصر؛ هنگامی که هر دکمه انتقال بین باز و بسته، کل لیستی از شاخص ها برای دکمه های در حال حاضر در آرایه بسته شده است به میزبان منتقل می شود.

از آنجا که تنها یک عنصر آرایه در هر فیلد آرایه report می شود، کلید های اصلاح کننده ( modifier keys ) باید به عنوان داده های bitmap گزارش شوند (گروهی از فیلدهای متغیر 1 بیتی)؛ برای مثال، کلید هایی مانند CTRL ،SHIFT ،ALT و کلید های GUI هشت-بیت تغییر بایت را در یک report صفحه کلید استاندارد تشکیل می دهند؛ اگرچه کدهای usage در جدول Usage به عنوان EO-E7 تعریف شده اند، usage به عنوان داده آرایه ارسال نمی شود؛ بایت اصلاح شده به شرح زیر تعریف شده است :

Report Format for Array Items

مثال زیر نشون میده که report ها تولید شدند توسط کاربر با تایپ کردن ALT+CTRL+DEL، با استفاده از یک bitmap برای اصلاح کنندگان و یک آرایه تنها برای تمام کلید های دیگر :

Report Format for Array Items

اگر report های متعدد برای این دستگاه وجود داشته باشد، هر report توسط Report ID منحصر به فرد آن پیش می آید :

Report Format for Array Items

اگر مجموعه ای از کلید ها یا دکمه ها نمی تواند متقابلا منحصر به فرد باشد، آنها باید به صورت یک bitmap یا به عنوان آرایه های چندگانه ارائه شوند؛ به عنوان مثال، کلید های عملکرد در یک صفحه کلید 101-کلیده ( کیبورد ها چیزی حدود 101 تا کلید/دکمه دارند ) گاهی به عنوان کلید های اصلاح کننده مورد استفاده قرار می گیرند، مثلا F1 A؛ در این حالت، حداقل به فیلد آرایه باید report شود در یک آرایه item، مثلا (Report Count (2.

 

محدودیت های Report

محدودیت های زیر به report ها و report handler اعمال می شود :

  • یک فیلد item نمی تواند در یک report بیش از 4 بایت باشد؛ به عنوان مثال، یک آیتم 32 بیتی باید برحسب مرز بایت آغاز شود تا این شرایط را برآورده کند.
  • تنها یک report مجاز هستش در هر USB transfer قرار بگیره.
  • یک گزارش ممکن است یک یا چند USB transaction را انجام دهد؛ به عنوان مثال، برنامه ای که دارای report های 10 بایت است حداقل دو USB transaction در یک دستگاه LS را انجام می دهد.
  • تمام report ها به جز طولانی ترین که wMaxPacketSize را برای endpoint می پردازند باید با یک بسته کوتاه خاتمه یابد؛ طولانی ترین گزارش یک بسته پایدار کوتاه نیاز ندارد.
  • هر مجموعه بالای سطح باید یک مجموعه کاربردی باشد و گزارشها ممکن است بیش از یک مجموعه بالای سطح را پوشش ندهند.
  • اگر گزارش های متعدد در یک مجموعه سطح بالا وجود داشته باشد، همه گزارش ها، به جز طولانی ترین، باید با یک بسته کوتاه خاتمه دهند.
  • گزارش همیشه بایت محور است. در صورت لزوم، گزارش ها با بیت (0) پاشیده می شوند تا مرز بعدی بایت رسیده باشد.

 

مثالی از Report

Report descriptor زیر، یک item با Input report تعریف کرده است :

HID Report Example

ساختار Input report دستگاه فوق، به صورت زیر خواهد بود :

توجه : مقادیر عددی چند-بایتی در گزارش ها در قالب little-endian نشان داده شده است؛ مقادیر Logical Minimum و Logical Maximum مشخص کننده محدوده مقادیری هستند که در گزارش ها پیدا میشوند؛ اگر Logical Minimum و Logical Maximum هردو مقادیری مثبت باشند، اونوقت وجود "بیت علامت" در فیلد report غیر ضروری هستش ( این بیت کجا هستش؟ پیداش نکردم )؛ در غیر این صورت، تمام مقادیر عدد صحیح ارزش های امضا شده در فرمت مکمل 2 را نشان می دهند؛ Floating point value ( اعداد اعشاری فک کنم منظورشه ) مجاز نیستند؛ کم ارزش ترین بیت داده، در بیت 0 ذخیره میشه و ...

توجه : چیزی که من فهیمدم در فرمت داده زیر، برا تعداد بایت های داده محدودیتی وجود نداره، تا هر اندازه فرمت داده که در Report Descriptor تعریف کردیم، اینجا میتونیم مقدار دیتا ها رو ارسال کنیم.

HID Report Example

جدول زیر از یک صفحه کلید با یک دستگاه اشاره گر یکپارچه برای نشان دادن نحوه استفاده از دو report برای یک دستگاه با یک interface استفاده می کند :

keyboard with an integrated pointing device

توجه : تنها آیتم های Input، Output و Feature ( آیتم های Collection نه ) داده ها را در report ارائه میدهند؛ این مثال چندین report را نشان می دهد، اما این interface برای دستگاه بوت قابل قبول نیست ( از interface های جداگانه برای دستگاه های keyboard و mouse استفاده کنید )

 

منبع این مطلب : 

1) Device Class Definition for Human Interface Devices (HID) Version 1.11

 

امیدوارم این مطلب مفید باشه براتون، این مطلب به مرور زمان اصلاح و ویرایش میشه؛ فعلا یا علی.

 

حدیث تصویری

گروه پرسش و پاسخ الکترونیکی در سروش
مهدی دمیرچیلو گوگل میفرماید : إِنَّ اللّه مَعَ السارِچین ( خداوند با سرچ کنندگان است )
ارسال دیدگاه
12

1) نظرات غیر فارسی به صورت خودکار حذف میشوند ( حداقل 5 حرف فارسی وارد کنید ).

2) به موارد درخواست پروژه/کد آماده و سوالاتی که بلد نباشم پاسخ داده نمیشه.

3) برای گزاشتن کدهاتون از این سایت استفاده کنید ( طبیعتا لینک کدتون رو باید برای من بفرستید! ) : debian

4) پسورد فایل های سایت : www.dmf313.ir

  1. Avatar

    مهمان

    محمد

    با سلام مجدد
    یه سایت گیر اوردم، شاید خوب باشه.
    https://www.pjrc.com/teensy/teensyduino.html
    https://www.pjrc.com/teensy/td_mouse.html
    https://www.pjrc.com/teensy/td_joystick.html
    https://www.pjrc.com/teensy/td_keyboard.html
    https://www.pjrc.com/teensy/td_serial.html

    انشا الله که مفید واقع بشه.
    و من الله توفیق، یا علی

  2. Avatar

    مهمان

    محمد

    سلام آقای مهدی
    با عرض خسته نباشید جانانه heart و قبولی عبادات، دوست عزیز این چند ماهه که ما رو روی این پروتکل کاشتی negative !!!
    بی صبرانه منتظریم خدا شاهده!! dash
    انشا الله هرچه زودتر این مطلب رو جمع جور کنین، چون در سطح کشورمون که تقریبا خیلی نادره این مطلب، در سطح جهان هم به سختی با این وظع فینگلیشیمون می شه مطلبی دستگیر کرد.
    و من الله توفیق، یا علی

  3. Avatar

    مهمان

    موسوی

    آقا ممنون بابت مطلب مفیدتون. ان شاء الله ادامه داشته باشه

  4. Avatar

    مهمان

    احمد

    خسته نباشی داداش
    من دیدم تو یکی از پستت دیدم که LCD N95 یا N96 بود اگه اشتباه نکرده باشم 🤔 ، رو راه انداخته بودی !
    حالا گفتم چرا این LCD های TFT ؟ گوشی من N86 بود، ال سی دی خیلی خفنی داشت (در رزولوشن 320×220، فکر کنم 🤔😁 )
    پیکسل های OLED داره ( مشکی رو از شب هم سیاه تر نشون میده! ) تو آفتاب هم تصویر واضحی داره، قیمتشم 28 تومنه !!!
    سوکتشم 24 پین هست خب زیاد تعریفشو کردم ولی خداییش باید ببینش چه تصویر معرکه ای داره
    خلاصه سرتونو درد آوردم، خواستم اینه که ببینید میشه با میکروکنترلر راش انداخت؟
    هر وقت وقت پیدا کردی یه نگاه بهش بنداز، ممنون میشم😊

    • مهدی دمیرچیلو

      نویسنده این مطلب

      مهدی دمیرچیلو

      سلام – هر نمایشگری که دیتاشیتش موجود باشه ( در حداقل ترین حالت ممکن ) امکان راه اندازیش وجود داره

      • Avatar

        مهمان

        احمد

        شرمنده بابت مزاحمت دوباره
        داداش یه نگاه به این لینک میشه بندازی، طرف سه تا پست زده و در آخر این OLED رو راه انداخته
        https://gobotronics.wordpress.com/tag/amdf001/
        ببین چیزی دستگیرت میشه؟
        ولی واقعا چیزیه که ارزشش رو داره، تا نبینیش باور نمیکنی! الانم آخر روزه و انگیزه هم در حد صفر!!! – هر وقت حوصله داشتی یه نگاه بنداز ممنونتون میشم، روز خوش

        • مهدی دمیرچیلو

          نویسنده این مطلب

          مهدی دمیرچیلو

          والا من دیگه قطعه محور کار نمیکنم، فعلا سرگرم پروتکول ها و طراحی قالب سایت هستش – بعید میدونم تا 6 ماه دیگه هم این usb رو بتونم کامل تموم کنم! good

          • Avatar

            مهمان

            احمد

            قلبمو شکوندی 😪

  5. Avatar

    مهمان

    qwerty13

    سلام،
    این مطلبتون رو که دیدم یاد این سوالم افتادم که با hid میشه حروف utf-08 رو وارد کامپیوتر کرد؟
    حتما میدونید که آردوینو کتابخونه ی hid داره، اما اون فقط حروف اسکی رو پشتیبانی میکنه. میشه کاری کرد که حروف فارسی رو هم پشتیبانی کنه؟

    • مهدی دمیرچیلو

      نویسنده این مطلب

      مهدی دمیرچیلو

      سلام – نمیدونم ولی یه روش به ذهنم میرسه اینه که میکرو در نقش کیبورد باشه و دیتای تغییر زبان فرستاده بشه تا زبان فارسی بشه و بعد کاراکتر ها رو ارسال کرد – مثل کیبورد واقعی – زبونو فارسی میکنی بعد مینویسی – نمیدونم – چیزی که الان به ذهنم میرسه …
      اسمت یکم آشناس برام.

      • مهدی دمیرچیلو

        نویسنده این مطلب

        مهدی دمیرچیلو

        فک کنم همینی که گفتم درست باشه – الان دارم رو کیبورد/کیپد مطالعه میکنم – به زودی یه پروژه ازش میزارم تو سایت.