# [USB]Obj-c  HID



## kollyv (17 Avril 2007)

Hello,

je vais démarrer un projet dont le but est de mettre à jour le firmware d'une télécommande reliée par USB et utilisant le driver HID.

Je ne connais malheureusment pas du totu objective-c. J'ai déjà réalisé une applic similiaire en C#. 

Après pas mal de recherche je me suis rendu compte qu'il n'existait pas grand chose pour le faire en obj-c.

Il me semble que le HID manager a été fait en C.  

J'ai quand meme trouvé une lib qui fait du binding avec l'api en C depuis obj-c

http://violasong.com/blog/2007/02/

Est ce que qqu connait un moyen de le faire. Sachant que je n'ai pas bcp de temps j'aimerais pouvoir éviter de tout refaire. Surtout qu'il va falloir comprendre objective-c.

Est ce que le faire avec Carbon (C++) serait plus adatpé.

J'utilise Xcode.

Merci d'avance


----------



## Dos Jones (17 Avril 2007)

Tu auras plus de chance dans "Développement sur Mac"


----------



## ntx (17 Avril 2007)

Le C peut être appelé sans restriction dans un programme en Obj-C. Donc pour l'interface tu peux choisir la techno que tu veux : Carbon ou Cocoa.


----------



## kollyv (17 Avril 2007)

Ok merci, je vais essayé d'y aller comme ca en utilisant IOHIDLib et je verrai bien au fur et a mesure. Je repasserai sans doute


----------



## kollyv (17 Avril 2007)

Je reviens demander un peu d'aide.

Je ne comprend pas bien comment utiliser ceci

http://developer.apple.com/documentation/Darwin/Reference/IOKit/IOHIDLib/index.html

Mais j'ai le sentiment que s'est se compliquer la vie puisqu'il existe le HID manager
http://developer.apple.com/document...onceptual/HID/basics/chapter_3_section_4.html

mais il ne s'agit pas d'objective-c.

Serait il possible d'utiliser cette api?


----------



## ntx (17 Avril 2007)

Oui, tu peux utiliser toutes les librairies C que tu trouves.


----------



## kollyv (18 Avril 2007)

Mais comment je dois faire vu qu'elles ne sont pas dans la même syntaxe. J'ai un peu du mal à m'y faire avec cet objec-c. Qqu n'aurait pas un exemple d'écriture/lecture sur un device hid?


----------



## ntx (18 Avril 2007)

Bon on reprend : l'Obj-C est une surcouche du C, qui apporte une notion de programmation objet. Les syntaxes du C et de l'Obj-C sont les MEMES pour ce qui concerne la programmation proc&#233;durale, seule les aspects "objet" sont sp&#233;cifiques &#224; l'obj-C.
Dans un programme en Obj-C rien n'interdit de mettre un printf ou un strlen, ou je ne sais quoi d'autre tir&#233; d'une librairie C quelconque.

Et pire encore tu peux m&#233;langer de l'Obj-C et du C++ : &#231;a s'appelle Obj-C++


----------



## kollyv (18 Avril 2007)

Bon alors super merci, je pense que cette information est un bon point de départ ;-)

Je ne voyais pas la chose comme ca. Je ne connais pas bien le C non plus... Bon bah je v essayer de m'en sortire avec tout ca

Encore merci pour ton aide


----------



## fedorinux (15 Juin 2007)

Bonjour,

je fais remonter ce topic car je cherche à communiquer avec un périphérique USB HID quelconque (je suis encore jeune développeur en électronique, accompagné par un jeune programmeur sous Delphi).
Bref, actuellement, j'ai une DLL sous XP et un bout de code pour Delphi (donc en Pascal) qui me permet d'envoyer et de recevoir des données à un périphérique USB HID uniquement en donnant son PID et VID.
Malheureusement pour moi, je bosse sous OSX et les logiciels sous XP ne sont pour moi qu'une "vision" (je ne touche pas à Delphi, je le connais mas je n'y touche pas).
Je voulais donc me mettre à développer avec Xcode (oui, moi qui ne touchais parfois qu'à l'assembleur et souvent au C, mais côté microcontrôleur). Un ami prof m'a conseillé de me mettre à Cocoa, ce que j'ai fait.
J'ai un peu tâtonné, trébuché, raté, planté... pendant 2-3 jours puis j'ai enfin saisi d'un seul coup le fonctionnement de l'Objective C (mais je dois encore me perfectionner).
Finalement, je voudrais faire un petit programme utile et surtout maîtriser la communication avec toutes mes créations en élec qui sont des périphériques USB HID.
Donc je voudrais connaître l'issue de la demande originale de ce topic et/ou avoir un peu d'aide pour parvenir à mon objectif.



Merci !


----------



## fedorinux (16 Juin 2007)

Je suis aussi preneur d'une bonne adresse (hormis le site de dev apple) o&#249; je peux trouver de l'aide (forums inclus).
M&#234;me en anglais, &#231; ne me g&#232;ne que rarement.


----------



## tatouille (16 Juin 2007)

La documentation est assez complete, dans /Developer/Examples/IOKit/usb et /Developer/Examples/Kernel/IOKit/usb tu trouveras des bases

il y a deux cas possibles :

1 - tu utilises les outils USB generiques car ton mat&#233;riel n'a rien de tr&#232;s sp&#233;cifique et utilise
des choses tr&#232;s g&#233;n&#233;riques auquel cas tu peux faire un client cocoa li&#233; au iokit qui te permettra
de communiquer avec ton device /et mat&#233;riel

2 - ton mat&#233;riel est vendor specifique et a besoin d 'implementer la class (abstract) HID, avec des v&#233;rifications et traductions sp&#233;cifiques, alors tu auras besoin de d&#233;velopper un petit driver, tu utiliseras alors les USBNotification a l'interieur de ton driver afin de pouvoir communiquer avec ton client dans le userspace (simple exemple mount/unmount)

si c'est le cas, voila un peu pr&#232;s les choses dont tu pourrais avoir besoin (un simple skeleton qui ressemblerait &#224; ceci) :

```
#ifndef IOUSBHIDDRIVER_H
#define IOUSBHIDDRIVER_H

//Provides a simple memory descriptor that allocates its own buffer memory.
#include <IOKit/IOBufferMemoryDescriptor.h>

//Time based event source mechanism.
#include <IOKit/IOTimerEventSource.h>

//IOHIDDevice defines a Human Interface Device (HID) object, which will interact with the HID 
// Manager by publishing static properties in the I/O Registry, and also by reporting HID events 
//through shared memory.
#include <IOKit/hid/IOHIDDevice.h>

/* take a look here
#include <IOKit/usb/IOUSBBus.h>
#include <IOKit/usb/IOUSBInterface.h>
#include <IOKit/usb/USB.h>
#include <IOKit/usb/IOUSBController.h>
*/
//This header contains the definition of the IOUSBControllerV2 class, which is a subclass of 
//IOUSBController. The IOUSBControllerV2 class supports high-speed (480 Mb/s) devices. 
#include <IOKit/usb/IOUSBControllerV2.h>

class USBSample : public IOHIDDevice
{
OSDeclareDefaultStructors(USBSample)
protected:
	IOUSBInterface 				*thisInterface;
	IOUSBDevice 				*thisDevice;
	IOUSBPipe 				*thisPipe;
	IOUSBCompletion     		       thisCompletion;
	IOBufferMemoryDescriptor 	       *thisBuffer;
 public:
    virtual bool start(IOService *provider);
    virtual void stop(IOService *provider);
    virtual bool terminate(IOOptionBits options = 0);
    virtual bool finalize(IOOptionBits options);
}

#endif  // IOUSBHIDDRIVER_H
```

mais je te conseilerais d'&#233;tendre un controller et de faire un pointer static sur MyHID
&#224; l'interieur de ta class maitresse


http://www.usb.org/developers/hidpage


----------



## fedorinux (17 Juin 2007)

Merci pour cette r&#233;ponse assez compl&#232;te (et le temps pass&#233; dessus)


J'ai donc quelques questions qui suivent :
Suite aux propositions 1 et 2, je me demande comment diff&#233;rencier un p&#233;riph&#233;rique qui n'a rien de particulier.
Clairement : j'utilise dans mes projets des microcontr&#244;leurs PIC18 (et DsPIC33). G&#233;n&#233;ralement les PIC18 que j'utilise ont un port USB. J'utilise donc un un firmware HID donn&#233; en exemple par Microchip que je modifie selon mes besoins. Bien souvent, mon p&#233;riph&#233;rique n'a absolument rien de sp&#233;cifique, c'est une interface utilisateur standard qui n'est reconnu comme rien (ni souris, ni joystick, ni clavier... rien du tout). Sous Windows, j'ai trouv&#233; une DLL mcHID.dll et un code "mod&#232;le" sous Delphi qui permet de communiquer avec mes interfaces uniquement &#224; l'aide du PID et VID qu'on pr&#233;cise dans le code (et c'est tr&#232;s pratique car je n'ose imaginer la difficult&#233; de devoir tout refaire &#224; chaque fois). En gros, on remplit un tableau char et hop, on envoie.
Je cherche donc &#224; refaire la m&#234;me chose avec XCode : remplir un tableau et envoyer mes octets par USB au p&#233;riph&#233;rique sp&#233;cifi&#233; par son VID et PID.

J'esp&#232;re que cette pr&#233;cision pour vous permettre de me lancer sur la bonne voie...




Vous avez aussi &#233;crit :


> La documentation est assez complete, dans /Developer/Examples/IOKit/usb et /Developer/Examples/Kernel/IOKit/usb tu trouveras des bases


Excusez moi pour mon ignorance, mes lorsque je vais dans ces r&#233;pertoires, je ne trouve pas de documentation.


EDIT : mes p&#233;riph&#233;riques sont en USB 2.0 Full Speed (12 Mbits/s)


----------



## fedorinux (18 Juin 2007)

Dans l'attente d'une réponse, j'ai tenté avec les exemples fournis.
Bref, USBSimpleExample trouve bien mon périphérique mais retourne cette erreur :

```
dealWithInterface: unable to open interface. ret = e00002c5
```

D'après ce que j'ai vu (IOReturn.h), cela indique que le périphérique est déjà utilisé.
Dès lors, je ne sais absolument pas quoi faire


----------



## tatouille (19 Juin 2007)

je pense que c'est un probleme de droit d'acces depuis le userspace

http://forum.microchip.com/printable.aspx?m=125158&mpage=2

as tu essay&#233; avec sudo ?

ou alors quelque chose de vendor specifique qui n'est pas support&#233; ?

http://lists.apple.com/archives/Usb/2006/Dec/msg00038.html

" The KVM   switch is reporting a pollingRate of 0 on the interrupt endpoint,    
which is not allowed by the USB 1.1 spec. By reading the whole    
thread, it's obvious that since 2002, Apple has changed the behavior    
so the interface can be created, but still won't allow the endpoint    
to be created, since it doesn't follow the USB specification.  

Has anything else changed since 2002, or is there a workaround, or am    
I just not going to be able to communicate with the interrupt    
endpoint on interface #1? Shame on the company that made this KVM    
switch for not adhering to the USB and HID specs!  "

tu n'as pas install&#233; xcode complet , re-telecharge sur l'ADC et r&#233;installe la totalit&#233;


----------



## fedorinux (19 Juin 2007)

Pour Xcode, je l'ai installé avec le CD que j'ai reçu via l'ADC student, donc je pense que tout y est.

J'ai lancé mon programme avec un sudo et j'obtiens la même erreur...


Mais dans le doute, je vais réinstaller Xcode complet.
Je vous tiens au courant.


----------



## fedorinux (20 Juin 2007)

J'ai bien réinstallé Xcode (téléchargement du fichier dmg + installations de tous les pkg).
Visiblement, ça na rien changé.


----------



## fedorinux (27 Juin 2007)

Je reviens &#224; la charge car &#231;a fait plus d'une semaine que je pi&#233;tine...

Je suis toujours preneur d'une aide, mais qui reste &#224; ma port&#233;e.

Alors j'ai tent&#233; plusieurs choses quand m&#234;me : 
Utilisation de libusb : j'ai plusieurs probl&#232;mes de fonctions non d&#233;clar&#233;es (usb-init, etc... avec une erreur zerolink) >> J'ai cherch&#233; dans tous le sens et j'ai finallement abandonn&#233;.
Essai de cr&#233;ation d'un driver vide pour que le syst&#232;me lib&#232;re mon p&#233;riph&#233;rique et donc pour revenir &#224; "USBSimple example" : le fichier kext se chargerai, impossible &#224; d&#233;charger et rien de lib&#233;r&#233;... >> J'ai cherch&#233; des exemples sur le net et dans les docs Apple : rien ne m'a aid&#233; donc abandon aussi.


----------



## kollyv (19 Juillet 2007)

Je vais poster ma solution:

J'ai utilisé le wrappeur DDHIdLib -> http://www.dribin.org/dave/blog/archives/2007/03/19/ddhidlib_10/

L'inisialisation:

```
@try{mDevices = [[DDHidDevice allDevices] retain] ;}@catch(NSException * e){}
        int i;    
        for (i = 0; i < [mDevices count]; i++ ){
            DDHidDevice * device =    (DDHidDevice*)[mDevices objectAtIndex: i];
            if ([device vendorId] == 7057 && [device productId] == 10 ){
                ewooDevice = device;
            }
        }
```
La callback pour la lecture: (ReaderReportCallback)

```
static void ReaderReportCallback(void *target, IOReturn result,
    void *refcon, void *sender, UInt32 size) {


}
```
L'initialisation de la callback:

```
ewooDeviceInterface = [ewooDevice deviceInterface];
    NSXThrowError((*ewooDeviceInterface)->open(ewooDeviceInterface,options));
    ioReturnValue = (*ewooDeviceInterface)->createAsyncPort(ewooDeviceInterface,&monPort);
    ioReturnValue = (*ewooDeviceInterface)->createAsyncEventSource(ewooDeviceInterface,&maLoop );
    rl = CFRunLoopGetCurrent ();
    ioReturnValue =  (*ewooDeviceInterface)->setInterruptReportHandlerCallback(ewooDeviceInterface, buffer,338, ReaderReportCallback,buffer,NULL);
    (*ewooDeviceInterface)->startAllQueues(ewooDeviceInterface);
    CFRunLoopAddSource(CFRunLoopGetCurrent(), maLoop, kCFRunLoopDefaultMode);
```

et pour écrire un report:


```
ioReturnValue = (*ewooDeviceInterface)->setReport(ewooDeviceInterface, reportType,12,start,64,2000,NULL,NULL,NULL);
```

Ce code fonctionne. Le problème que je rencontre est le suivant:

Sur MAC intel: j'ai une corrupte stack si je ne lance pas l'application avec ROSETTA.

SI j'enlève l'initilisation de la callback ca fonctionne.

Est ce que qqu peut m'aider?


----------



## tatouille (21 Juillet 2007)

juste un peu de lecture et je pense que cela ira

http://developer.apple.com/hardwaredrivers/customusbdrivers.html


----------



## kollyv (23 Juillet 2007)

Ok!! C'est tout bon. J'ai suivit le tutoriel et repris les exemples à la lettre ça marche  Je ne comprendrai jamais quel était le pb qui demandé l'émulation de rosetta mais pour l'instant ca me va.

Merci bcp

@+


----------



## kollyv (23 Juillet 2007)

Je développe un nouveau projet qui a besoin de communiquer avec le HID également. L'initilisation de la callback et l'écriture des reports fonctionne mais impossible d'entrer dans la callback lors d'un read quand l'initilisation est threadé.

Je lance un thread qui check si le périphérique est bien connecté. S'il n'as pas encore été connecté, l'initilisation se fait depuis ce thread mais du coup je ne lit plus rien. Pas d'erreurs non plus à la compilation

Qqu a une soluce?


----------



## tatouille (27 Juillet 2007)

il te faut un Event thread synchronization object


----------



## kollyv (27 Juillet 2007)

Ok merci, je vois pas très bien, mais je vais chercher la autour. Il y a aussi la possiblité de récupérer un événement lorsqu'un quelquonc usb est connecté et de lancer l'initilisation a ce moment la


----------



## kollyv (30 Juillet 2007)

> Event thread synchronization object



Salut Tatouille, pourrais tu me donner un peu plus d'explication à ce propos? Je ne vois pas  bien le rapport avec mon problème.

En initilisation le device, callbacl, etc depuis le main il n'y a pas de problème. 

Je thread la méthode d'initilisation, pas d'erreur mais aucune lecture dans la callback

Merci pour ton aide


----------



## tatouille (30 Juillet 2007)

IOWorkLoop, IOEventSources


----------



## kollyv (30 Juillet 2007)

Ok je vois ce qu'il faut faire, j'ai pu trouver qq exemple sur internet. C'est donc limiter l'accès à un seul thread au hardware grâce à un IOWorkLoop.

Cependand je n'arrive pas à l'utiliser car IOWorkLoop.h n'est pas dans l'IOKit. Si je le cherche je vois qu'il est par contre dans le framework kernel.framework. Mais si j'importe celui-ci, le compilateur me génère bcp d'erreurs dans ce framework ...

ha quel misère :/


----------



## tatouille (30 Juillet 2007)

toutes les superclasses du IOKIT l'implementent n'utilise pas kernel.framework


----------



## kollyv (30 Juillet 2007)

hum mais je ne comprend pas bien. Il y a déjà le framework IOKit à plusieurs endroits différent. Ca veut dire que j'ai utilisé un framework qui n'implémente pas tout le IOKit. 

Dans ce cas, lequel est ce que je dois prendre?


----------



## tatouille (31 Juillet 2007)

non tu as l'interface IOKit osfmach du noyeau (platform-specific)

kernel/IO 

http://developer.apple.com/documentation/Darwin/Reference/KernelIOKitFramework/index.html

et l'interface "public" (platform-independent)
 du IOKit et son imlementation

------ IOKit.framework
----------IOKern
-----------MACH

tu ne peux pas acceder aux symboles de ton noyeau (enfin si mais ce n'est pas le sujet)
tu dois utiliser IOKit.framework / KPI (Kernel programming interface)

http://developer.apple.com/documentation/DeviceDrivers/Conceptual/WritingDeviceDriver/index.html


http://developer.apple.com/DOCUMENT...//apple_ref/doc/uid/TP0000011-CH204-TPXREF101


----------



## kollyv (31 Juillet 2007)

Je vais regarder ça, merci bcp pour ton aide!


----------



## kollyv (13 Août 2007)

J'ai repris le problème. Ca fait un bon moment que je cherche sans trop trouver :/ Je ne comprend pas ou trouver ce framework. l'IOKit.framework ne contient pas de iowoorkloop.h. Après une recherche sur le hd, seulement kernel.framework/iokit contient le fichier. Faut il le télécharger qq part? Toutes mes libs sont pourtant à jour


----------



## kollyv (13 Août 2007)

je dois apparemment utiliser le framework kernel.framework qui contient iokit. Cependant le compilo plante en me marquant cette erreur:

can't locate framework for: -framework Kernel

Je ne vois pas bien ou lui décrire un autre chemin pour ce framework et pk le faire, qqu aurait une idée?


----------



## kollyv (13 Août 2007)

Bon ben j'ai résolu mon pb, j'ai utilisé 
	
	



```
[self performSelectorOnMainThread:@selector(setupDongle) withObject:self waitUntilDone:YES];
```

et ca marche


----------

