Tuesday, September 18, 2012

Alla ricerca del senso del lavoro per un capitalismo responsabile

http://www.repubblica.it/speciali/repubblica-delle-idee/edizione2012/2012/09/18/news/il_senso_del_lavoro_il_capitalismo_pu_riscoprire_la_virt-42765109/?rss

Alla ricerca del senso del lavoro
per un capitalismo responsabile

Il neoliberismo ha teorizzato l'assenza di ogni responsabilità sociale per l'impresa. L'assunzione del rischio individuale è stata posta al centro del modello economico occidentale, e il profitto a breve termine è diventato l'unico metro di misura del successo Ecco qualche proposta per uscire dalla crisi attuale

di WILL HUTTON
Alla ricerca del senso del lavoro per un capitalismo responsabile
Leader e intellettuali di ogni orientamento politico oggi discutono della possibilità di un nuovo approccio all'organizzazione e alla gestione del sistema economico. Per rispondere a questa esigenza, gli imprenditori dovrebbero almeno riconoscere di essere parte integrante delle società in cui operano. Il capitalismo affonda le sue radici in due tradizioni: il protestantesimo individualistico della Riforma e l'affermazione della "sfera pubblica" di origine illuministica.

Negli ultimi trent'anni anni si è assistito a un sistematico tentativo, per iniziativa del neoconservatorismo americano, di negare il ruolo dell'Illuminismo per concentrarsi esclusivamente sull'individualismo. L'assunzione del rischio individuale è stata posta al centro (o presunto tale) del modello economico occidentale, e il profitto a breve termine è diventato l'unico metro di misura del successo. Il concetto di "uomo economico razionale" si è sviluppato a partire da questo approccio intellettuale quasi-ideologico, assurgendo a dogma del sistema
imprenditoriale occidentale. Di conseguenza, la maggior parte delle organizzazioni considera una priorità la creazione di condizioni che favoriscano l'autonomia manageriale, la massimizzazione del valore per gli azionisti e la mercificazione del lavoro, anziché il riconoscimento dell'interdipendenza tra impresa e società, o del ruolo delle finalità e del valore sociale all'interno dell'impresa stessa.

Non bisogna dimenticare, tuttavia, che alle prime organizzazioni imprenditoriali di rilievo  -  la Compagnia olandese delle Indie orientali, per esempio  -  fu concesso il privilegio della costituzione in società commerciali in cambio della garanzia di concreti benefici pubblici. Esse furono costituite, cioè, per una finalità da cui erano intente a ricavare profitti. Per la Compagnia olandese delle Indie orientali, l'obiettivo era quello di regolamentare il mercato esistente al fine di massimizzare i ricavi per le Repubbliche olandesi, impegnate a combattere i loro rivali e a impedire ad altre nazioni europee di penetrare nelle loro rotte commerciali. La Compagnia inglese delle Indie orientali fu costituita allo stesso modo. I profitti erano funzionali al raggiungimento di uno scopo.

La tradizione delle corporazioni che esprimono uno scopo commerciale con un valore pubblico e sociale è stata sviluppata da quei filosofi illuministi secondo cui sono l'interconnessione sociale e i rapporti all'interno della comunità a dare senso alla nostra vita. Per Rousseau, ad esempio, quest'ultimo può essere raggiunto attraverso la vita di comunità e l'interazione sociale, che consentono agli individui di maturare un sentimento di solidarietà in rapporti trasparenti con gli altri. Nel 1776 Adam Smith scrisse 'La ricchezza delle nazioni', seguita dalla Teoria dei sentimenti morali, e concepì le due opere come un tutt'uno. Il capitalismo non può essere disgiunto né dal senso né dai princìpi morali.

Prima della secolarizzazione della società moderna, la religione assolveva al compito di dare un senso alla vita delle persone esprimendo valori e princìpi morali in grado di tenere unite le comunità. Più di un secolo fa il grande sociologo francese Emile Durkheim sostenne che, contestualmente al declino della religione, il suo ruolo tradizionale di fonte di significato sarebbe stato sostituito dalle organizzazioni capitalistiche. Oggi il lavoro e
le organizzazioni contribuiscono in modo ancor più decisivo a definire il nostro status sociale e lo scopo della nostra esistenza come individui.

Tuttavia, le teorie dominanti in materia di organizzazione aziendale non riconoscono questo vincolo, bensì pongono l'accento sulla razionalità dell'individualismo economico intesa come principio morale valido in sé, senza un contesto sociale di riferimento. E quando gli attori imprenditoriali e istituzionali negano la necessità di uno scopo di più ampio respiro, quel vuoto viene riempito dal mantra dell'efficienza, della flessibilità e della razionalità degli uomini e delle donne economici, il che alimenta un senso di alienazione, disadattamento e angoscia. A fronte di questo svuotamento morale, la corsa sfrenata al benessere materiale rimane l'unica fonte di senso: di qui la caccia a profitti sempre più esorbitanti. In seno alla cerchia dei super ricchi  -  dai Ceo alle star del football  -  nessuno ormai può spendere tutti i milioni che percepisce in busta paga; quel che la società non può concedersi, invece, è un segno di valore.

Troppo spesso le organizzazioni moderne non riescono a mettere gli individui in condizione di dare un senso al proprio lavoro. Perché ciò sia possibile, le stesse organizzazioni devono esprimere valori e finalità in cui i lavoratori si identifichino, in un certo senso legittimando e affermando il loro legame con le comunità di appartenenza e con l'universo morale a cui fanno riferimento. Con la deificazione del profitto e del valore per gli azionisti quali obiettivi strategici d'impresa, tuttavia, la "creazione di senso" va perduta.

L'appello per un capitalismo responsabile lanciato lo scorso anno da Ed Miliband è imperniato sull'idea che le organizzazioni moderne debbano trovare un equilibrio tra l'imperativo del profitto e la responsabilità sociale. Miliband auspica un capitalismo più virtuoso, improntato all'impegno per un'impresa produttiva, non al business fine a se stesso. E traccia una netta distinzione tra il "produttore", il "predatore" e l'"asset stripper" (chi acquisisce una società per poi frazionarla a fini speculativi, ndt). All'inizio il suo messaggio è stato oggetto di critiche e commenti scettici; nove mesi dopo, sono sempre più numerosi gli imprenditori e i politici che cercano a modo loro di dire le stesse cose.

All'atto pratico, tuttavia, non è così semplice tracciare una linea di demarcazione tra capitalismo buono e cattivo, poiché molte organizzazioni rivestono i loro gretti interessi commerciali con pretese finalità sociali di ampio respiro. Il caso Enron, per esempio, ha fatto balzare la questione dell'etica e della responsabilità sociale in cima alle priorità delle imprese. Prima dello scandalo, la responsabilità d'impresa era un principio "a combustione lenta", propugnato da molti ma praticato da pochi. Oggi è al centro di preoccupati dibattiti nelle sale di consigli di amministrazione europei e statunitensi. La governance aziendale, il ruolo dei direttori non esecutivi, la
correttezza delle convenzioni in materia di revisione contabile e il codice etico dei lavoratori sono oggetto di un'analisi più attenta che mai.

Si tratta di una sfida, ma anche di un'opportunità. Oggi le aziende hanno la possibilità senza precedenti di riconquistare il ruolo di fonte di motivazione e, in quanto tali, di diventare parte della soluzione anziché del problema. In virtù del sempre più evidente valore pratico dell'impresa responsabile, occorre apprendere nuove regole del gioco che consentano alle organizzazioni di operare in modo tale da promuovere l'equità, la coesione sociale e il benessere  -  e, non ultimo, la sostenibilità nel lungo periodo.
© Riproduzione riservata (18 settembre 2012)

Monday, September 03, 2012


Cito dal sito del Corriere.it

Padre Georg Sporschill, il confratello gesuita che lo intervistò in Conversazioni notturne a Gerusalemme , e Federica Radice hanno incontrato Martini l'8 agosto: «Una sorta di testamento spirituale. Il cardinale Martini ha letto e approvato il testo».
Come vede lei la situazione della Chiesa?
«La Chiesa è stanca, nell'Europa del benessere e in America. La nostra cultura è invecchiata, le nostre Chiese sono grandi, le nostre case religiose sono vuote e l'apparato burocratico della Chiesa lievita, i nostri riti e i nostri abiti sono pomposi. Queste cose però esprimono quello che noi siamo oggi? (...) Il benessere pesa. Noi ci troviamo lì come il giovane ricco che triste se ne andò via quando Gesù lo chiamò per farlo diventare suo discepolo. Lo so che non possiamo lasciare tutto con facilità. Quanto meno però potremmo cercare uomini che siano liberi e più vicini al prossimo. Come lo sono stati il vescovo Romero e i martiri gesuiti di El Salvador. Dove sono da noi gli eroi a cui ispirarci? Per nessuna ragione dobbiamo limitarli con i vincoli dell'istituzione».
Chi può aiutare la Chiesa oggi?
«Padre Karl Rahner usava volentieri l'immagine della brace che si nasconde sotto la cenere. Io vede nella Chiesa di oggi così tanta cenere sopra la brace che spesso mi assale un senso di impotenza. Come si può liberare la brace dalla cenere in modo da far rinvigorire la fiamma dell'amore? Per prima cosa dobbiamo ricercare questa brace. Dove sono le singole persone piene di generosità come il buon samaritano? Che hanno fede come il centurione romano? Che sono entusiaste come Giovanni Battista? Che osano il nuovo come Paolo? Che sono fedeli come Maria di Magdala? Io consiglio al Papa e ai vescovi di cercare dodici persone fuori dalle righe per i posti direzionali. Uomini che siano vicini ai più poveri e che siano circondati da giovani e che sperimentino cose nuove. Abbiamo bisogno del confronto con uomini che ardono in modo che lo spirito possa diffondersi ovunque».
Che strumenti consiglia contro la stanchezza della Chiesa?
«Ne consiglio tre molto forti. Il primo è la conversione: la Chiesa deve riconoscere i propri errori e deve percorrere un cammino radicale di cambiamento, cominciando dal Papa e dai vescovi. Gli scandali della pedofilia ci spingono a intraprendere un cammino di conversione. Le domande sulla sessualità e su tutti i temi che coinvolgono il corpo ne sono un esempio. Questi sono importanti per ognuno e a volte forse sono anche troppo importanti. Dobbiamo chiederci se la gente ascolta ancora i consigli della Chiesa in materia sessuale. La Chiesa è ancora in questo campo un'autorità di riferimento o solo una caricatura nei media? Il secondo la Parola di Dio. Il Concilio Vaticano II ha restituito la Bibbia ai cattolici. (...) Solo chi percepisce nel suo cuore questa Parola può far parte di coloro che aiuteranno il rinnovamento della Chiesa e sapranno rispondere alle domande personali con una giusta scelta. La Parola di Dio è semplice e cerca come compagno un cuore che ascolti (...). Né il clero né il Diritto ecclesiale possono sostituirsi all'interiorità dell'uomo. Tutte le regole esterne, le leggi, i dogmi ci sono dati per chiarire la voce interna e per il discernimento degli spiriti. Per chi sono i sacramenti? Questi sono il terzo strumento di guarigione. I sacramenti non sono uno strumento per la disciplina, ma un aiuto per gli uomini nei momenti del cammino e nelle debolezze della vita. Portiamo i sacramenti agli uomini che necessitano una nuova forza? Io penso a tutti i divorziati e alle coppie risposate, alle famiglie allargate. Questi hanno bisogno di una protezione speciale. La Chiesa sostiene l'indissolubilità del matrimonio. È una grazia quando un matrimonio e una famiglia riescono (...). L'atteggiamento che teniamo verso le famiglie allargate determinerà l'avvicinamento alla Chiesa della generazione dei figli. Una donna è stata abbandonata dal marito e trova un nuovo compagno che si occupa di lei e dei suoi tre figli. Il secondo amore riesce. Se questa famiglia viene discriminata, viene tagliata fuori non solo la madre ma anche i suoi figli. Se i genitori si sentono esterni alla Chiesa o non ne sentono il sostegno, la Chiesa perderà la generazione futura. Prima della Comunione noi preghiamo: "Signore non sono degno..." Noi sappiamo di non essere degni (...). L'amore è grazia. L'amore è un dono. La domanda se i divorziati possano fare la Comunione dovrebbe essere capovolta. Come può la Chiesa arrivare in aiuto con la forza dei sacramenti a chi ha situazioni familiari complesse?»
Lei cosa fa personalmente?
«La Chiesa è rimasta indietro di 200 anni. Come mai non si scuote? Abbiamo paura? Paura invece di coraggio? Comunque la fede è il fondamento della Chiesa. La fede, la fiducia, il coraggio. Io sono vecchio e malato e dipendo dall'aiuto degli altri. Le persone buone intorno a me mi fanno sentire l'amore. Questo amore è più forte del sentimento di sfiducia che ogni tanto percepisco nei confronti della Chiesa in Europa. Solo l'amore vince la stanchezza. Dio è Amore. Io ho ancora una domanda per te: che cosa puoi fare tu per la Chiesa?».

Monday, August 27, 2012

Up!

Un film di Pete Docter, Bob Peterson. Con Edward Asner, Christopher Plummer, Jordan Nagai, Bob Peterson, Delroy Lindo.

continua»
Animazione, Ratings: Kids, durata 104 min. - USA 2009. - Walt Disney uscita giovedì 15 ottobre 2009
In una sala cinematografica si proietta un cinegiornale su un esploratore, Charles Muntz, che è tornato dall'America del Sud con lo scheletro di un uccello che la scienza ufficiale qualifica come falso. Muntz riparte per dimostrare la sua onestà. Un bambino occhialuto, Carl, è in sala. Muntz è il suo eroe. Incontrerà una bambina, Ellie, che ha la sua stessa passione. I due cresceranno insieme e si sposeranno. Un giorno però Carl si ritrova vedovo con la sua villetta circondata da un cantiere e con il sogno che i contrattempi della vita non hanno mai permesso a lui ed Ellie di realizzare: una casa in prossimità delle cascate citate da Muntz come luogo della sua scoperta. Un giorno un Giovane Esploratore bussa alla sua porta. Sarà con lui che Carl, senza volerlo, comincerà a realizzare il sogno.

Romanzo di una strage

Un film di Marco Tullio Giordana. Con Valerio Mastandrea, Pierfrancesco Favino, Michela Cescon, Laura Chiatti, Fabrizio Gifuni.

continua»
Drammatico, durata 129 min. - Italia 2012. - 01 Distribution uscita venerdì 30 marzo 2012.
Milano, dicembre 1969. Giuseppe Pinelli è un ferroviere milanese. Marito, padre e anarchico anima e ispira il Circolo Anarchico Ponte della Ghisolfa. Luigi Calabresi è vice-responsabile della Polizia Politica della Questura di Milano. Marito, padre e commissario segue e sorveglia le opinioni politiche della sinistra extraparlamentare. Impegnati con intelligenza e rigore su fronti opposti, si incontrano e scontrano tra un corteo e una convocazione. L'esplosione alla Banca Nazionale dell'Agricoltura di Piazza Fontana, in cui muoiono diciassette persone e ne restano ferite ottantotto, provoca un collasso alla nazione e una tensione in quella ‘corrispondenza cordiale'. Convocato la sera dell'attentato e interrogato per tre giorni, Pinelli muore in circostanze misteriose, precipitando dalla finestra dell'Ufficio di Calabresi. Assente al momento del tragico evento, il commissario finisce per diventarne responsabile e vittima. Perseguitato con implacabile risolutezza dagli esponenti di Lotta Continua, ‘implicato' dalla Questura e abbandonato dai ‘dirigenti', continuerà a indagare sulla strage, scoprendo il coinvolgimento della destra neofascista veneta e la responsabilità di apparati dello Stato. Una promozione e un trasferimento rifiutati confermeranno la sua integrità, determinandone il destino.

Il Rosso e il Blu

http://www.mymovies.it/film/2012/ilrossoeilblu/
Un film di Giuseppe Piccioni. Con Margherita Buy, Riccardo Scamarcio, Roberto Herlitzka, Silvia D'Amico, Davide Giordano.

continua»
Drammatico, - Italia 2012. - Teodora Film uscita venerdì 21 settembre 2012.
La storia di un insegnante e i suoi studenti, ambientato in una scuola superiore di Roma. Qui vi è un anziano professore di storia dell'arte molto cinico che ha perso il senso del suo lavoro.
Prendono parte anche un giovane supplente alla sua prima volta da insegnante, una preside impeccabile e rigorosa e dei ragazzi che sfidano la sorte per dimostrare di essere adulti. Il rosso e il blu è tratto dall'omonimo libro di Marco Lodoli, pubblicato da Einaudi. La sceneggiatura è stata scritta dal regista insieme a Francesca Manieri.

Thursday, August 26, 2010

Riporto uno scritto di Baricco apparso su Repubblica il 26/08/2010
http://www.repubblica.it/spettacoli-e-cultura/2010/08/26/news/barbari_2026-6516602/?rss

Il capovolgimento dei concetti di profondità-superficialità mi pare estremamente attuale, se non addirittura urgente.

2026, la vittoria dei barbari
Uno scrittore viaggia nel futuro, alla scoperta di un'èra dominata dalla superficialità. Con una sorpresa: non sarà poi così male
di ALESSANDRO BARICCO

2026, la vittoria dei barbari

Ci crediate o no, questo articolo l'ho scritto nel luglio 2026, cioè fra sedici anni. Diciamo che mi son portato un po' avanti col lavoro. Prendetela così.
Ecco l'articolo.
Alle volte si scrivono libri che sono come duelli: finita la sparatoria guardi chi è rimasto in piedi, e se non sei tu, hai perso. Quando ho scritto I barbari, venti anni fa, poi mi son guardato attorno ed erano ancora tutti lì, belli in piedi. Aveva tutta l'aria di una disfatta, ma la cosa non mi quadrava. Allora mi son seduto e ho aspettato. Il gioco è stato vederli cadere uno ad uno, tardivi ma stecchiti. Ci vuole solo pazienza. Alle volte agonizzano molto elegantemente. Alcuni franano a terra tutto d'un colpo. Non la prenderei come una vittoria, probabile che cadano per consunzione loro, non per i miei proiettili: ma certo non avevo mirato male, mi viene da dire, a parziale consolazione.
L'ultimo che ho visto crollare, dopo aver vacillato a lungo con grande lentezza e dignità, mi ha emozionato, perché lo conoscevo bene. Credo di avere in passato anche lavorato per lui (con pistole caricate a parole, come sempre). Più che uno, è una: la profondità. Il concetto di profondità, la pratica della profondità, la passione per la profondità. Forse qualcuno se li ricorda, erano animali ancora in forma, ai tempi dei Barbari. Li alimentava l'ostinata convinzione che il senso delle cose fosse collocato in una cella segreta, al riparo dalle più facili evidenze, conservato nel freezer di una oscurità remota, accessibile solo alla pazienza, alla fatica, all'indagine ostinata. Le cose erano alberi - se ne sondavano le radici. Si risaliva nel tempo, si scavava nei significati, si lasciavano sedimentare gli indizi. Perfino nei sentimenti si aspirava a quelli profondi, e la bellezza stessa la si voleva profonda, come i libri, i gesti, i traumi, i ricordi, e alle volte gli sguardi. Era un viaggio, e la sua meta si chiamava profondità.

La ricompensa era il senso, che si chiamava anche senso ultimo, e ci concedeva la rotondità di una frase a cui, anni fa, credo di aver sacrificato una marea di tempo e luce: il senso ultimo e profondo delle cose.
Non so quando, esattamente, ma a un certo punto questo modo di vedere le cose ha iniziato a sembrarci inadatto. Non falso: inadatto. Il fatto è che il senso consegnatoci dalla profondità si rivelava troppo spesso inutile, e talvolta perfino dannoso. Così, come in una sorta di timido preludio, ci è accaduto di mettere in dubbio che esistesse poi davvero un "senso ultimo e profondo delle cose". Provvisoriamente ci si orientò per definizioni più soft che sembravano rispecchiare meglio la realtà dei fatti. Che il senso fosse un divenire mai fissabile in una definizione ci sembrò, ad esempio, un buon compromesso. Ma oggi credo si possa dire che semplicemente non osavamo abbastanza, e che l'errore non era tanto credere in un senso ultimo quanto il relegarlo in profondità. Quel che cercavamo esisteva, ma non era dove pensavamo.

Non era lì per una ragione sconcertante che la mutazione avvenuta negli ultimi trent'anni ci ha buttato in faccia, emanando uno dei suoi verdetti più affascinanti e dolorosi: la profondità non esiste, è un'illusione ottica. È l'infantile traduzione in termini spaziali e morali di un desiderio legittimo: collocare ciò che abbiamo di più prezioso (il senso) in un luogo stabile, al riparo dalle contingenze, accessibile solo a sguardi selezionati, attingibile solo attraverso un cammino selettivo. Così si nascondono i tesori. Ma nel nasconderlo avevamo creato un Eldorado dello spirito, la profondità, che in realtà non sembra mai essere esistito, e che alla lunga sarà ricordato come una delle utili menzogne che gli umani si sono raccontati. Piuttosto scioccante, non c'è santo.

Infatti uno dei traumi cui la mutazione ci ha sottoposto è proprio il trovarsi a vivere in un mondo privo di una dimensione a cui eravamo abituati, quella della profondità. Ricordo che in un primo momento le menti più avvedute avevano interpretato questa curiosa condizione come un sintomo di decadenza: registravano, non a torto, la sparizione improvvisa di una buona metà del mondo che conoscevano: oltretutto, quella che veramente contava, che conteneva il tesoro. Da qui l'istintiva inclinazione a interpretare gli eventi in termini apocalittici: l'invasione di un'orda barbarica che non disponendo del concetto di profondità stava ridisponendo il mondo nell'unica residua dimensione di cui era capace, la superficialità. Con conseguente dispersione disastrosa di senso, di bellezza, di significati - di vita. Non era un modo idiota di leggere le cose, ma ora sappiamo con una certa esattezza che era un modo miope: scambiava l'abolizione della profondità con l'abolizione del senso. Ma in realtà quello che stava accadendo, tra mille difficoltà e incertezze, era che, abolita la profondità, il senso si stava spostando ad abitare la superficie delle evidenze e delle cose. Non spariva, si spostava. La reinvenzione della superficialità come luogo del senso è una delle imprese che abbiamo compiuto: un lavoretto d'artigianato spirituale che passerà alla storia.

Sulla carta, i rischi erano enormi, ma va ricordato che la superficie è il luogo della stupidità solo per chi crede nella profondità come luogo del senso. Dopo che i barbari (cioè noi) hanno smascherato questa credenza, collegare automaticamente superficie e insignificanza è diventato un riflesso meccanico che tradisce un certo rincoglionimento. Dove molti vedevano una semplice resa alla superficialità, molti altri hanno intuito uno scenario ben differente: il tesoro del senso, che era relegato in una cripta segreta e riservata, ora si distribuiva sulla superficie del mondo, dove la possibilità di ricomporlo non coincideva più con una discesa ascetica nel sottosuolo, regolata da un'élite di sacerdoti, ma da una collettiva abilità nel registrare e collegare tessere del reale. Non suona poi tanto male. Soprattutto sembra più adatto alle nostre abilità e ai nostri desideri. Per gente incapace di stare ferma e di concentrarsi, ma in compenso velocissima nello spostarsi e nel collegare frammenti, il campo aperto della superficie sembra la sede ideale dove giocarsi la partita della vita: perché mai dovremmo giocarcela, e perderla, in quei cunicoli nel sottosuolo che si ostinavano a insegnarci a scuola?

Così non sembriamo aver rinunciato a un senso, nobile e alto, delle cose: ma abbiamo iniziato a inseguirlo con una tecnica diversa, cioè muovendoci sulla superficie del mondo con una velocità e un talento che gli umani non hanno mai conosciuto. Ci siamo orientati a formare figure di senso mettendo in costellazione punti del reale attraverso cui passiamo con inedita agilità e leggerezza. L'immagine del mondo che i media restituiscono, la geografia di ideali che la politica ci propone, l'idea di sapere che il mondo digitale ci mette a disposizione non hanno ombra di profondità: sono collezioni di evidenze sottili, perfino fragili, che organizziamo in figure di una certa potenza. Le usiamo per capire il mondo. Perdiamo capacità di concentrazione, non riusciamo a fare un gesto alla volta, scegliamo sempre la velocità a discapito dell'approfondimento: l'incrocio di questi difetti genera una tecnica di percezione del reale che cerca sistematicamente la simultaneità e la sovrapposizione degli stimoli: è ciò che noi chiamiamo fare esperienza. Nei libri, nella musica, in ciò che chiamiamo bello guardandolo o ascoltandolo, riconosciamo sempre più spesso l'abilità a pronunciare l'emozione del mondo semplicemente illuminandola, e non riportandola alla luce: è l'estetica che ci piace coltivare, quella per cui qualsiasi confine tra arte alta e arte bassa va scomparendo, non essendoci più un basso e un alto, ma solo luce e oscurità, sguardi e cecità. Viaggiamo velocemente e fermandoci poco, ascoltiamo frammenti e mai tutto, scriviamo nei telefoni, non ci sposiamo per sempre, guardiamo il cinema senza più entrare nei cinema, ascoltiamo reading in rete invece che leggere i libri, facciamo lente code per mangiare al fast food, e tutto questo andare senza radici e senza peso genera tuttavia una vita che ci deve apparire estremamente sensata e bella se con tanta urgenza e passione ci preoccupiamo, come mai nessuno prima di noi nella storia del genere umano, di salvare il pianeta, di coltivare la pace, di preservare i monumenti, di conservare la memoria, di allungare la vita, di tutelare i più deboli e di difendere il lardo di Colonnata. In tempi che ci piace immaginare civili, bruciavano le biblioteche o le streghe, usavano il Partenone come deposito di esplosivi, schiacciavano vite come mosche nella follia delle guerre, e spazzavano via popoli interi per farsi un po' di spazio. Erano spesso persone che adoravano la profondità.
La superficie è tutto, e in essa è scritto il senso. Meglio: in essa siamo capaci di tracciare un senso. E da quando abbiamo maturato questa abilità, è quasi con imbarazzo che subiamo gli inevitabili sussulti del mito della profondità: oltre ogni misura ragionevole patiamo le ideologie, gli integralismi, ogni arte troppo alta e seria, qualsiasi sfacciata pronuncia di assoluto. Probabilmente abbiamo anche torto, ma sono cose che ricordiamo saldate in profondità a ragioni e sacerdozi indiscutibili che ora sappiamo fondati sul nulla, e ne siamo ancora offesi - forse spaventati. Per questo oggi suona kitsch ogni simulazione di profondità e in fondo sottilmente cheap qualsiasi concessione alla nostalgia. La profondità sembra essere diventata una merce di scarto per i vecchi, i meno avveduti e i più poveri.

Vent'anni fa avrei avuto paura a scrivere frasi del genere. Mi era chiaro perfettamente che stavamo giocando col fuoco. Sapevo che i rischi erano enormi e che in una simile mutazione ci giocavamo un patrimonio immenso. Scrivevo I barbari, ma intanto sapevo che lo smascheramento della profondità poteva generare il dominio dell'insignificante. E sapevo che la reinvenzione della superficialità generava spesso l'effetto indesiderato di sdoganare, per un equivoco, la pura stupidità, o la ridicola simulazione di un pensiero profondo. Ma alla fine, quel che è accaduto è stato soltanto il frutto delle nostre scelte, del talento e della velocità delle nostre intelligenze. La mutazione ha generato comportamenti, cristallizzato parole d'ordine, ridistribuito i privilegi: ora so che in tutto ciò è sopravvissuta la promessa di senso che a suo modo il mito della profondità tramandava. Sicuramente tra coloro che sono stati più svelti a capire e gestire la mutazione ce ne sono molti che non conoscono quella promessa, né sono capaci di immaginarla, né sono interessati a tramandarla. Da essi stiamo ricevendo un mondo brillante senza futuro. Ma come sempre è successo, ostinata e talentuosa è stata anche la cultura della promessa, e capace di estorcere al disinteresse dei più la deviazione della speranza, della fiducia, dell'ambizione. Non credo sia stolto ottimismo registrare il fatto che oggi, nel 2026, una cultura del genere esiste, sembra più che solida, e spesso presidia le cabine di comando della mutazione. Da questi barbari stiamo ricevendo un'impaginazione del mondo adatta agli occhi che abbiamo, un design mentale appropriato ai nostri cervelli, e un plot della speranza all'altezza dei nostri cuori, per così dire. Si muovono a stormi, guidati da un rivoluzionario istinto a creazioni collettive e sovrapersonali, e per questo mi ricordano la moltitudine senza nomi dei copisti medievali: in quel loro modo strano, stanno copiando la grande biblioteca nella lingua che è nostra. È un lavoro delicato, e destinato a collezionare errori. Ma è l'unico modo che conosciamo per consegnare in eredità, a chi verrà, non solo il passato, ma anche un futuro.

(26 agosto 2010) © Riproduzione riservata

Tuesday, June 08, 2010

USB communications with Zebra printers in C#

The best way to create your own application which uses a Zebra printer is to send ZPL commands directly to the printer. This is easy on RS232 or TCP/IP connections, but it's not so simple on USB, because Zebra does not offer (at least officially) an SDK which exposes APIs for USB.

I've found on the internet several articles about how to communicate with a Zebra printer through a USB connection. Most of them refer to an article by Microsoft's Knowledge Base which explains how to send raw data to the printer driver. Apart from performance issues, this is useful only if your communication is monodirectional (from the PC to the printer). It can be enough for most printers, but if you are using an RFID printer this is definitely not acceptable, as you probably need to read data from the printer in order to check the result of RFID operations for logging/printing purposes.

I searched the web for a C# based solution and I've found an excellent implementation of a communication framework using different media, like USB. It is part of a larger project hosted on SourceForge called ZBar (a collection of MS VS.NET components, controls and class libraries to aid development of printing functionality in .NET applications that make use of some barcode printers).

I took some classes from that project and with some modifications I got a nice USB stream for Zebra printers, which can be easily used to send and receive ZPL (or other scripting language) commands. The printer driver must be installed on the PC, but commands do not go through it.

Here are the files. Notice that they work both on x86 and x64 systems, but on x64 they must be compiled with the x86 option.

I collected all these files in this post because it was (at least for me) hard to find a solution for this issue, which is all in all very basic (just an I/O class for a printer!)



//-------------------------------
// ZebraUsbStream.cs
//-------------------------------
using System;
using System.Collections.Generic;
using System.Text;
using System.IO;
using Zebra.Printing;

namespace RfidPrinter
{
///


/// Stream subclass which incorporates low-level USB access to Zebra printers
///

public class ZebraUsbStream : Stream
{
UsbPrinterConnector usb;

public ZebraUsbStream(string port)
{
usb = new UsbPrinterConnector(port);
usb.IsConnected = true;
base.ReadTimeout = usb.ReadTimeout;
base.WriteTimeout = usb.WriteTimeout;
}

public ZebraUsbStream()
{
System.Collections.Specialized.NameValueCollection devs =
UsbPrinterConnector.EnumDevices(true, true, false);

if (devs.Count < 1)
throw new Exception("No Zebra printers found");

usb = new UsbPrinterConnector(devs[0].ToString());
usb.IsConnected = true;
}


public override bool CanRead
{
get { return true; }
}

public override bool CanSeek
{
get { return false; }
}

public override bool CanWrite
{
get { return true; }
}

public override bool CanTimeout
{
get { return true; }
}

public override void Flush()
{
;
}

public override long Length
{
get { throw new NotSupportedException(); }
}

public override long Position
{
get
{
throw new NotSupportedException();
}
set
{
throw new NotSupportedException();
}
}

public override int Read(byte[] buffer, int offset, int count)
{
return usb.Read(buffer, offset, count);
}

public override long Seek(long offset, SeekOrigin origin)
{
throw new NotSupportedException();
}

public override void SetLength(long value)
{
throw new NotSupportedException();
}

public override void Write(byte[] buffer, int offset, int count)
{
usb.Send(buffer, offset, count);
}

protected override void Dispose(bool disposing)
{
base.Dispose(disposing);
usb.IsConnected = false;
}

public override void Close()
{
base.Close();
if (usb.IsConnected)
usb.IsConnected = false;
}

public override int ReadTimeout
{
get
{
return usb.ReadTimeout;
}
set
{
usb.ReadTimeout = value;
}
}

public override int WriteTimeout
{
get
{
return usb.WriteTimeout;
}
set
{
usb.WriteTimeout = value;
}
}
}
}


//-------------------------------
//FileIO.cs
//-------------------------------


#region License
/* ---------------------------------------------------------------------------
* Creative Commons License
* http://creativecommons.org/licenses/by/2.5/au/
*
* Attribution 2.5 Australia
*
* You are free:
*
* - to copy, distribute, display, and perform the work
* - to make derivative works
* - to make commercial use of the work
*
* Under the following conditions:
*
* Attribution: You must attribute the work in the manner specified by the
* author or licensor.
*
* For any reuse or distribution, you must make clear to others the license
* terms of this work. Any of these conditions can be waived if you get
* permission from the copyright holder. Your fair use and other rights
* are in no way affected by the above.
*
* This is a human-readable summary of the Legal Code (the full license).
* http://creativecommons.org/licenses/by/2.5/au/legalcode
* ------------------------------------------------------------------------ */

/* ---------------------------------------------------------------------------
* Special Note
*
* A special mention and thanks to the contributions of several parties in
* blogging and publishing this complex API.
*
* P/Invoke .NET - http://www.pinvoke.net
*
* MSDN Magazine
*
* ------------------------------------------------------------------------ */
#endregion License

// $Header: /cvsroot/z-bar/msvs/zbar/Zebra.Printing/fileio.cs,v 1.4 2006/11/16 10:55:04 vinorodrigues Exp $

#if WindowsCE || PocketPC
#define WINCE
#endif

using System;
using System.Runtime.InteropServices;
using System.Threading;

#if WINCE
#error This module is not intended for Mobile platform
#endif

namespace Zebra.Printing
{
internal class FileIO
{

internal const int INVALID_HANDLE_VALUE = -1;

internal const int ERROR_FILE_NOT_FOUND = 2;
internal const int ERROR_INVALID_NAME = 123;
internal const int ERROR_ACCESS_DENIED = 5;
internal const int ERROR_IO_PENDING = 997;
internal const int ERROR_IO_INCOMPLETE = 996;

internal class NullClass
{
public NullClass()
{
throw new Exception("Cannot create instance of NullClass");
}
}

#region CreateFile

[Flags]
internal enum FileAccess : uint // from winnt.h
{
GENERIC_READ = 0x80000000,
GENERIC_WRITE = 0x40000000,
GENERIC_EXECUTE = 0x20000000,
GENERIC_ALL = 0x10000000
}

[Flags]
internal enum FileShareMode : uint // from winnt.h
{
FILE_SHARE_READ = 0x00000001,
FILE_SHARE_WRITE = 0x00000002,
FILE_SHARE_DELETE = 0x00000004
}

internal enum FileCreationDisposition : uint // from winbase.h
{
CREATE_NEW = 1,
CREATE_ALWAYS = 2,
OPEN_EXISTING = 3,
OPEN_ALWAYS = 4,
TRUNCATE_EXISTING = 5
}

[Flags]
internal enum FileAttributes : uint // from winnt.h
{
FILE_ATTRIBUTE_READONLY = 0x00000001,
FILE_ATTRIBUTE_HIDDEN = 0x00000002,
FILE_ATTRIBUTE_SYSTEM = 0x00000004,
FILE_ATTRIBUTE_DIRECTORY = 0x00000010,
FILE_ATTRIBUTE_ARCHIVE = 0x00000020,
FILE_ATTRIBUTE_DEVICE = 0x00000040,
FILE_ATTRIBUTE_NORMAL = 0x00000080,
FILE_ATTRIBUTE_TEMPORARY = 0x00000100,
FILE_ATTRIBUTE_SPARSE_FILE = 0x00000200,
FILE_ATTRIBUTE_REPARSE_POINT = 0x00000400,
FILE_ATTRIBUTE_COMPRESSED = 0x00000800,
FILE_ATTRIBUTE_OFFLINE = 0x00001000,
FILE_ATTRIBUTE_NOT_CONTENT_INDEXED = 0x00002000,
FILE_ATTRIBUTE_ENCRYPTED = 0x00004000,

// from winbase.h
FILE_FLAG_WRITE_THROUGH = 0x80000000,
FILE_FLAG_OVERLAPPED = 0x40000000,
FILE_FLAG_NO_BUFFERING = 0x20000000,
FILE_FLAG_RANDOM_ACCESS = 0x10000000,
FILE_FLAG_SEQUENTIAL_SCAN = 0x08000000,
FILE_FLAG_DELETE_ON_CLOSE = 0x04000000,
FILE_FLAG_BACKUP_SEMANTICS = 0x02000000,
FILE_FLAG_POSIX_SEMANTICS = 0x01000000,
FILE_FLAG_OPEN_REPARSE_POINT = 0x00200000,
FILE_FLAG_OPEN_NO_RECALL = 0x00100000,
FILE_FLAG_FIRST_PIPE_INSTANCE = 0x00080000
}

[DllImport("kernel32.dll", SetLastError = true)]
internal static extern IntPtr CreateFile(
string lpFileName,
FileAccess dwDesiredAccess,
FileShareMode dwShareMode,
IntPtr lpSecurityAttributes,
FileCreationDisposition dwCreationDisposition,
FileAttributes dwFlagsAndAttributes,
IntPtr hTemplateFile);

#endregion CreateFile

#region CloseHandle

[DllImport("kernel32.dll", SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
internal static extern bool CloseHandle(IntPtr hObject);

#endregion CloseHandle

#region GetOverlappedResult

[DllImport("kernel32.dll", SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
internal static extern bool GetOverlappedResult(
IntPtr hFile,
/* IntPtr */ ref System.Threading.NativeOverlapped lpOverlapped,
out uint nNumberOfBytesTransferred,
bool bWait);

#endregion GetOverlappedResult

#region WriteFile

[DllImport("kernel32.dll", SetLastError = true, EntryPoint = "WriteFile")]
[return: MarshalAs(UnmanagedType.Bool)]
internal static extern bool WriteFile0(
IntPtr hFile,
[MarshalAs(UnmanagedType.LPArray)]
byte[] lpBuffer,
uint nNumberOfBytesToWrite,
out uint lpNumberOfBytesWritten,
NullClass lpOverlapped);

[DllImport("kernel32.dll", SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
internal static extern bool WriteFile(
IntPtr hFile,
[MarshalAs(UnmanagedType.LPArray)] byte[] lpBuffer,
uint nNumberOfBytesToWrite,
out uint lpNumberOfBytesWritten,
[In] ref System.Threading.NativeOverlapped lpOverlapped);

[DllImport("kernel32.dll", SetLastError = true)]
internal static extern int WriteFileEx(
IntPtr hFile,
[MarshalAs(UnmanagedType.LPArray)] byte[] lpBuffer,
int nNumberOfBytesToWrite,
[In] ref System.Threading.NativeOverlapped lpOverlapped,
[MarshalAs(UnmanagedType.FunctionPtr)] IOCompletionCallback callback
);

#endregion WriteFile

#region ReadFile

[DllImport("kernel32.dll", SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
internal static extern bool ReadFile(
IntPtr hFile,
[MarshalAs(UnmanagedType.LPArray)] [Out] byte[] lpBuffer,
uint nNumberOfBytesToRead,
out uint lpNumberOfBytesRead,
[In] ref System.Threading.NativeOverlapped lpOverlapped);

[DllImport("kernel32.dll", SetLastError = true, EntryPoint = "ReadFile")]
[return: MarshalAs(UnmanagedType.Bool)]
internal static extern bool ReadFile0(
IntPtr hFile,
[MarshalAs(UnmanagedType.LPArray)] [Out] byte[] lpBuffer,
uint nNumberOfBytesToRead,
out uint lpNumberOfBytesRead,
NullClass lpOverlapped);

[DllImport("kernel32.dll", SetLastError = true)]
internal static extern int ReadFileEx(
IntPtr hFile,
[MarshalAs(UnmanagedType.LPArray)] byte[] lpBuffer,
int nNumberOfBytesToRead,
[In] ref System.Threading.NativeOverlapped lpOverlapped,
[MarshalAs(UnmanagedType.FunctionPtr)] IOCompletionCallback callback);

#endregion ReadFile

}
}


//-------------------------------
// PrinterConnector.cs
//-------------------------------

#region License
/* ---------------------------------------------------------------------------
* Creative Commons License
* http://creativecommons.org/licenses/by/2.5/au/
*
* Attribution 2.5 Australia
*
* You are free:
*
* - to copy, distribute, display, and perform the work
* - to make derivative works
* - to make commercial use of the work
*
* Under the following conditions:
*
* Attribution: You must attribute the work in the manner specified by the
* author or licensor.
*
* For any reuse or distribution, you must make clear to others the license
* terms of this work. Any of these conditions can be waived if you get
* permission from the copyright holder. Your fair use and other rights
* are in no way affected by the above.
*
* This is a human-readable summary of the Legal Code (the full license).
* http://creativecommons.org/licenses/by/2.5/au/legalcode
* ------------------------------------------------------------------------ */
#endregion License

// $Header: /cvsroot/z-bar/msvs/zbar/Zebra.Printing/Connect.cs,v 1.7 2006/11/16 10:55:04 vinorodrigues Exp $

using System;
using System.Collections.Generic;
using System.Text;

namespace Zebra.Printing
{

public abstract class PrinterConnector
{

protected abstract void SetConnected(bool value);

protected abstract bool GetConnected();

public bool IsConnected
{
get { return GetConnected(); }
set { SetConnected(value); }
}

public static readonly int DefaultReadTimeout = 200;

private int readTimeout = DefaultReadTimeout;

public int ReadTimeout
{
get { return readTimeout; }
set { readTimeout = value; }
}

public static readonly int DefaultWriteTimeout = 200;

private int writeTimeout = DefaultWriteTimeout;

public int WriteTimeout
{
get { return writeTimeout; }
set { writeTimeout = value; }
}

/* public bool Connect()
{
SetConnected(true);
return GetConnected();
} */

/* public void Disconnect()
{
SetConnected(false);
} */

public int Send(byte[] buffer)
{
return Send(buffer, 0, buffer.Length);
}

public abstract bool BeginSend();

public abstract void EndSend();

public abstract int Send(byte[] buffer, int offset, int count);

public virtual bool CanRead()
{
return false;
}

///
/// Reads data from the incomming connection.
///

/// populated data buffer or null if empty/unsuccessful
/// Number of bytes read or -1 if unsuccessful
public abstract int Read(byte[] buffer, int offset, int count);

}

}



//-------------------------------
// SetupApi.cs
//-------------------------------

#region License
/* ---------------------------------------------------------------------------
* Creative Commons License
* http://creativecommons.org/licenses/by/2.5/au/
*
* Attribution 2.5 Australia
*
* You are free:
*
* - to copy, distribute, display, and perform the work
* - to make derivative works
* - to make commercial use of the work
*
* Under the following conditions:
*
* Attribution: You must attribute the work in the manner specified by the
* author or licensor.
*
* For any reuse or distribution, you must make clear to others the license
* terms of this work. Any of these conditions can be waived if you get
* permission from the copyright holder. Your fair use and other rights
* are in no way affected by the above.
*
* This is a human-readable summary of the Legal Code (the full license).
* http://creativecommons.org/licenses/by/2.5/au/legalcode
* ------------------------------------------------------------------------ */

/* ---------------------------------------------------------------------------
* Special Note
*
* A special mention and thanks to the contributions of several parties in
* blogging and publishing this complex API. Converting to C# was not easy!
*
* The "setupapi.h" file from the Microsoft DDK for Windows XP SP2
*
* Peter Skarpetis for this blog "GETTING A HANDLE ON USBPRINT.SYS"
* http://blog.peter.skarpetis.com
*
* The Code Project - http://www.codeproject.com
*
* P/Invoke .NET - http://www.pinvoke.net
*
* ------------------------------------------------------------------------ */
#endregion License

// $Header: /cvsroot/z-bar/msvs/zbar/Zebra.Printing/setupapi.cs,v 1.4 2006/12/28 10:54:21 vinorodrigues Exp $

#if WindowsCE || PocketPC
#define WINCE
#endif

#if WINCE
#error This module is not intended for Mobile platform
#endif

using System;
using System.Text;
using System.Runtime.InteropServices;

namespace Zebra.Printing
{

internal class SetupApi
{

#region Consts

internal const UInt32 DIGCF_DEFAULT = 0x00000001; // only valid with DIGCF_DEVICEINTERFACE
internal const UInt32 DIGCF_PRESENT = 0x00000002;
internal const UInt32 DIGCF_ALLCLASSES = 0x00000004;
internal const UInt32 DIGCF_PROFILE = 0x00000008;
internal const UInt32 DIGCF_DEVICEINTERFACE = 0x00000010;

internal const UInt32 SPDRP_DEVICEDESC = 0x00000000; // DeviceDesc (R/W)
internal const UInt32 SPDRP_HARDWAREID = 0x00000001; // HardwareID (R/W)
internal const UInt32 SPDRP_COMPATIBLEIDS = 0x00000002; // CompatibleIDs (R/W)
internal const UInt32 SPDRP_UNUSED0 = 0x00000003; // unused
internal const UInt32 SPDRP_SERVICE = 0x00000004; // Service (R/W)
// internal const UInt32 SPDRP_UNUSED1 = 0x00000005; // unused
// internal const UInt32 SPDRP_UNUSED2 = 0x00000006; // unused
internal const UInt32 SPDRP_CLASS = 0x00000007; // Class (R--tied to ClassGUID)
internal const UInt32 SPDRP_CLASSGUID = 0x00000008; // ClassGUID (R/W)
internal const UInt32 SPDRP_DRIVER = 0x00000009; // Driver (R/W)
internal const UInt32 SPDRP_CONFIGFLAGS = 0x0000000A; // ConfigFlags (R/W)
internal const UInt32 SPDRP_MFG = 0x0000000B; // Mfg (R/W)
internal const UInt32 SPDRP_FRIENDLYNAME = 0x0000000C; // FriendlyName (R/W)
internal const UInt32 SPDRP_LOCATION_INFORMATION = 0x0000000D; // LocationInformation (R/W)
internal const UInt32 SPDRP_PHYSICAL_DEVICE_OBJECT_NAME = 0x0000000E; // PhysicalDeviceObjectName (R)
internal const UInt32 SPDRP_CAPABILITIES = 0x0000000F; // Capabilities (R)
internal const UInt32 SPDRP_UI_NUMBER = 0x00000010; // UiNumber (R)
internal const UInt32 SPDRP_UPPERFILTERS = 0x00000011; // UpperFilters (R/W)
internal const UInt32 SPDRP_LOWERFILTERS = 0x00000012; // LowerFilters (R/W)
internal const UInt32 SPDRP_BUSTYPEGUID = 0x00000013; // BusTypeGUID (R)
internal const UInt32 SPDRP_LEGACYBUSTYPE = 0x00000014; // LegacyBusType (R)
internal const UInt32 SPDRP_BUSNUMBER = 0x00000015; // BusNumber (R)
internal const UInt32 SPDRP_ENUMERATOR_NAME = 0x00000016; // Enumerator Name (R)
internal const UInt32 SPDRP_SECURITY = 0x00000017; // Security (R/W, binary form)
internal const UInt32 SPDRP_SECURITY_SDS = 0x00000018; // Security (W, SDS form)
internal const UInt32 SPDRP_DEVTYPE = 0x00000019; // Device Type (R/W)
internal const UInt32 SPDRP_EXCLUSIVE = 0x0000001A; // Device is exclusive-access (R/W)
internal const UInt32 SPDRP_CHARACTERISTICS = 0x0000001B; // Device Characteristics (R/W)
internal const UInt32 SPDRP_ADDRESS = 0x0000001C; // Device Address (R)
internal const UInt32 SPDRP_UI_NUMBER_DESC_FORMAT = 0x0000001D; // UiNumberDescFormat (R/W)
internal const UInt32 SPDRP_DEVICE_POWER_DATA = 0x0000001E; // Device Power Data (R)
internal const UInt32 SPDRP_REMOVAL_POLICY = 0x0000001F; // Removal Policy (R)
internal const UInt32 SPDRP_REMOVAL_POLICY_HW_DEFAULT = 0x00000020; // Hardware Removal Policy (R)
internal const UInt32 SPDRP_REMOVAL_POLICY_OVERRIDE = 0x00000021; // Removal Policy Override (RW)
internal const UInt32 SPDRP_INSTALL_STATE = 0x00000022; // Device Install State (R)
internal const UInt32 SPDRP_MAXIMUM_PROPERTY = 0x00000023; // Upper bound on ordinals

#endregion Consts

#region Structs

[StructLayout(LayoutKind.Sequential)]
internal struct SP_DEVINFO_DATA
{
///
/// Size of structure in bytes
///

public Int32 cbSize;
///
/// GUID of the device interface class
///

public Guid classGuid;
///
/// Handle to this device instance
///

public Int32 devInst;
///
/// Reserved; do not use.
///

public UIntPtr reserved;
};

[StructLayout(LayoutKind.Sequential)]
internal struct SP_DEVICE_INTERFACE_DATA
{
///
/// Size of the structure, in bytes
///

public Int32 cbSize;
///
/// GUID of the device interface class
///

public Guid interfaceClassGuid;
///
///
///

public UInt32 flags;
///
/// Reserved; do not use.
///

public UIntPtr reserved;
};

[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto, Pack = 1)]
public struct SP_DEVICE_INTERFACE_DETAIL_DATA
{
public UInt32 cbSize;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 1024)] // will never be more than 256 in length
public string devicePath;
}

public class NullClass
{
public NullClass()
{
throw new Exception("Cannot create instance of NullClass");
}
}

#endregion Structs

#region DLLImports

[DllImport("setupapi.dll", CharSet = CharSet.Auto)]
internal static extern IntPtr SetupDiGetClassDevs(
ref Guid ClassGuid,
[MarshalAs(UnmanagedType.LPTStr)]
String Enumerator,
IntPtr hwndParent,
UInt32 Flags);

[DllImport(@"setupapi.dll", CharSet=CharSet.Auto, SetLastError = true)] // from PInvoke.net
internal static extern UInt16 SetupDiDestroyDeviceInfoList( IntPtr hDevInfo );

[DllImport(@"setupapi.dll", CharSet = CharSet.Auto, SetLastError = true)] // from PInvoke.net
internal static extern Boolean SetupDiEnumDeviceInterfaces(
IntPtr hDevInfo,
ref SP_DEVINFO_DATA devInfo,
ref Guid interfaceClassGuid,
UInt32 memberIndex,
ref SP_DEVICE_INTERFACE_DATA deviceInterfaceData );

[DllImport(@"setupapi.dll", CharSet = CharSet.Auto, SetLastError = true)]
internal static extern Boolean SetupDiEnumDeviceInterfaces(
IntPtr hDevInfo,
int zero_devInfo, // used for 0 (Zero)
ref Guid interfaceClassGuid,
UInt32 memberIndex,
ref SP_DEVICE_INTERFACE_DATA DeviceInterfaceData );

[DllImport(@"setupapi.dll", CharSet = CharSet.Auto, SetLastError = true, EntryPoint = "SetupDiGetDeviceInterfaceDetail")]
internal static extern Boolean SetupDiGetDeviceInterfaceDetail0(
IntPtr hDevInfo,
ref SP_DEVICE_INTERFACE_DATA deviceInterfaceData,
ref SP_DEVICE_INTERFACE_DETAIL_DATA deviceInterfaceDetailData, // OPTIONAL
UInt32 deviceInterfaceDetailDataSize,
/* out UInt32 */ NullClass requiredSize, // OPTIONAL
ref SP_DEVINFO_DATA deviceInfoData); // OPTIONAL

[DllImport(@"setupapi.dll", CharSet = CharSet.Auto, SetLastError = true, EntryPoint = "SetupDiGetDeviceInterfaceDetail")]
internal static extern Boolean SetupDiGetDeviceInterfaceDetail0(
IntPtr hDevInfo,
ref SP_DEVICE_INTERFACE_DATA deviceInterfaceData,
NullClass deviceInterfaceDetailData, // OPTIONAL
UInt32 deviceInterfaceDetailDataSize,
out UInt32 requiredSize, // OPTIONAL
NullClass deviceInfoData); // OPTIONAL

/* [DllImport(@"setupapi.dll", CharSet = CharSet.Auto, SetLastError = true)]
internal static extern Boolean SetupDiGetDeviceInterfaceDetail(
IntPtr hDevInfo,
ref SP_DEVICE_INTERFACE_DATA deviceInterfaceData,
Int32 zero_deviceInterfaceDetailData, // used for 0 (Zero)
UInt32 zero_deviceInterfaceDetailDataSize,
out UInt32 requiredSize,
Int32 zero_deviceInfoData); // used for 0 (Zero) */ // KEEP

[DllImport(@"setupapi.dll", CharSet = CharSet.Auto, SetLastError = true, EntryPoint = "SetupDiGetDeviceRegistryProperty")]
internal static extern Boolean SetupDiGetDeviceRegistryProperty0(
IntPtr hDevInfo,
ref SP_DEVINFO_DATA deviceInfoData,
UInt32 property,
/* out IntPtr */ NullClass propertyRegDataType, // OPTIONAL
StringBuilder propertyBuffer,
UInt32 propertyBufferSize,
/* out IntPtr */ NullClass requiredSize); // OPTIONAL

[DllImport(@"setupapi.dll", CharSet = CharSet.Auto, SetLastError = true, EntryPoint = "SetupDiGetDeviceRegistryProperty")] // overloaded for null refs
internal static extern Boolean SetupDiGetDeviceRegistryProperty0(
IntPtr hDevInfo,
ref SP_DEVINFO_DATA deviceInfoData,
UInt32 property,
out IntPtr propertyRegDataType, // OPTIONAL
NullClass propertyBuffer,
UInt32 propertyBufferSize, // set to 0 (Zero)
out UInt32 requiredSize); // OPTIONAL

#endregion DLLImports

}
}




//-------------------------------
// UsbPrinterconnector.cs
//-------------------------------

#region License
/* ---------------------------------------------------------------------------
* Creative Commons License
* http://creativecommons.org/licenses/by/2.5/au/
*
* Attribution 2.5 Australia
*
* You are free:
*
* - to copy, distribute, display, and perform the work
* - to make derivative works
* - to make commercial use of the work
*
* Under the following conditions:
*
* Attribution: You must attribute the work in the manner specified by the
* author or licensor.
*
* For any reuse or distribution, you must make clear to others the license
* terms of this work. Any of these conditions can be waived if you get
* permission from the copyright holder. Your fair use and other rights
* are in no way affected by the above.
*
* This is a human-readable summary of the Legal Code (the full license).
* http://creativecommons.org/licenses/by/2.5/au/legalcode
* ------------------------------------------------------------------------ */

/* ---------------------------------------------------------------------------
* Special Note
*
* A special mention and thanks to the contributions of several parties in
* blogging and publishing this complex API. Converting to C# was not easy!
*
* The "setupapi.h" file from the Microsoft DDK for Windows XP SP2
*
* Peter Skarpetis for this blog "GETTING A HANDLE ON USBPRINT.SYS"
* http://blog.peter.skarpetis.com
*
* The Code Project - http://www.codeproject.com
*
* P/Invoke .NET - http://www.pinvoke.net
*
* ------------------------------------------------------------------------ */
#endregion License

// $Header: /cvsroot/z-bar/msvs/zbar/Zebra.Printing/ConUsb.cs,v 1.7 2006/12/28 10:54:21 vinorodrigues Exp $

#if WindowsCE || PocketPC
#define WINCE
#endif

#if WINCE
#error This module is not intended for Mobile platform
#endif

using System;
using System.Text;
using System.Runtime.InteropServices;
using System.ComponentModel;
using System.Collections.Specialized;
using System.IO;
using Microsoft.Win32;
using System.Threading;

namespace Zebra.Printing
{

///
/// Connector leveraging usbmon.dll/usbprint.sys.

/// Note: This cannot be used in more than one process at a time, so if the spooler is running you cannot use it.
///

public class UsbPrinterConnector : PrinterConnector
{

#region EnumDevices

static Guid GUID_DEVICEINTERFACE_USBPRINT = new Guid(
0x28d78fad, 0x5a12, 0x11D1,
0xae, 0x5b, 0x00, 0x00, 0xf8, 0x03, 0xa8, 0xc2);
// static IntPtr INVALID_HANDLE_VALUE = (IntPtr)(-1);

public static NameValueCollection EnumDevices()
{
return EnumDevices(true);
}

public static NameValueCollection EnumDevices(bool presentOnly)
{
return EnumDevices(presentOnly, true);
}

public static NameValueCollection EnumDevices(bool presentOnly, bool zebraOnly)
{
return EnumDevices(presentOnly, zebraOnly, true);
}

public static NameValueCollection EnumDevices(bool PresentOnly, bool ZebraOnly, bool fullDetail)
{
NameValueCollection res = new NameValueCollection();
String name, path, desc, port;

Guid intfce;
IntPtr devs;
SetupApi.SP_DEVINFO_DATA devinfo = new SetupApi.SP_DEVINFO_DATA();
SetupApi.SP_DEVICE_INTERFACE_DATA devinterface = new SetupApi.SP_DEVICE_INTERFACE_DATA();
SetupApi.SP_DEVICE_INTERFACE_DETAIL_DATA interface_detail;
UInt32 devcount;
UInt32 size;

RegistryKey regKey, subKey;

intfce = GUID_DEVICEINTERFACE_USBPRINT;

UInt32 flags = SetupApi.DIGCF_DEVICEINTERFACE;
if (PresentOnly)
flags |= SetupApi.DIGCF_PRESENT;

devs = SetupApi.SetupDiGetClassDevs(ref intfce,
null,
IntPtr.Zero,
flags);
if (devs == (IntPtr)FileIO.INVALID_HANDLE_VALUE)
return null;

devcount = 0;
devinterface.cbSize = Marshal.SizeOf(typeof(SetupApi.SP_DEVICE_INTERFACE_DATA));

while (SetupApi.SetupDiEnumDeviceInterfaces(
devs,
0,
ref intfce,
devcount,
ref devinterface))
{
devcount++;

SetupApi.SetupDiGetDeviceInterfaceDetail0(
devs,
ref devinterface,
null,
0,
out size,
null);

if ((size > 0) &&
(size <= (Marshal.SizeOf(typeof(SetupApi.SP_DEVICE_INTERFACE_DETAIL_DATA))) - sizeof(UInt32)))
{

interface_detail = new SetupApi.SP_DEVICE_INTERFACE_DETAIL_DATA();
interface_detail.cbSize = (UInt32)(sizeof(UInt32) + sizeof(Char)); // Wow! This is a gotcha!

devinfo = new SetupApi.SP_DEVINFO_DATA();
devinfo.cbSize = Marshal.SizeOf(typeof(SetupApi.SP_DEVINFO_DATA));

if (SetupApi.SetupDiGetDeviceInterfaceDetail0(
devs,
ref devinterface,
ref interface_detail,
size,
null,
ref devinfo))
{
path = interface_detail.devicePath.ToString();
name = GetDeviceRegistryProperty(devs, ref devinfo, SetupApi.SPDRP_LOCATION_INFORMATION);
if (fullDetail)
{
desc = "";
port = "";

if (path.StartsWith("\\\\?\\"))
{
string key = "##?#" + path.Substring(4);

try
{
regKey = Registry.LocalMachine.OpenSubKey("SYSTEM\\CurrentControlSet\\Control\\DeviceClasses\\" +
GUID_DEVICEINTERFACE_USBPRINT.ToString("B"));
try
{
subKey = regKey.OpenSubKey(key);
if (subKey != null)
{
subKey = subKey.OpenSubKey("#\\Device Parameters");
desc = subKey.GetValue("Port Description").ToString();
port = subKey.GetValue("Port Number").ToString();
subKey.Close();
}
}
finally
{
regKey.Close();
}
}
catch
{
// do nothing
}
}

if (ZebraOnly && (!desc.StartsWith("Zebra")))
continue;

res.Add(name, path);
res.Add(name, desc);
res.Add(name, port);
}
else
res.Add(name, path);
}
else
throw new Win32Exception(Marshal.GetLastWin32Error());
}

}
SetupApi.SetupDiDestroyDeviceInfoList(devs);

return res;
}

private static String GetDeviceRegistryProperty(IntPtr hDevInfo,
ref SetupApi.SP_DEVINFO_DATA deviceInfoData,
UInt32 property)
{
IntPtr dataType = IntPtr.Zero;
uint size;
StringBuilder buffer;

SetupApi.SetupDiGetDeviceRegistryProperty0(
hDevInfo,
ref deviceInfoData,
property,
out dataType,
null,
0,
out size);

if (size > 0)
{
buffer = new StringBuilder((int)size);

if (SetupApi.SetupDiGetDeviceRegistryProperty0(
hDevInfo,
ref deviceInfoData,
property,
null,
buffer,
size,
null))
{
return buffer.ToString();
}
else
throw new Win32Exception(Marshal.GetLastWin32Error());
}
else
return String.Empty;
}

#endregion EnumDevices

private string interfaceName;

private IntPtr usbHandle = IntPtr.Zero;

public static readonly uint ReadBufferSize = 512;

private byte[] readBuffer;

///
/// Constructor
///

///
public UsbPrinterConnector(string InterfaceName)
: base()
{
if (!InterfaceName.StartsWith("\\"))
{
NameValueCollection plist = EnumDevices(true, false, false);
if (plist.GetValues(InterfaceName) != null)
InterfaceName = plist.GetValues(InterfaceName)[0];
else
throw new Exception("Cannot locate USB device");
}
this.interfaceName = InterfaceName;
}

///
/// Destructor
///

~UsbPrinterConnector()
{
SetConnected(false);
}

protected override void SetConnected(bool value)
{
if (value)
{
if ((int)usbHandle > 0)
SetConnected(false);

/* C++ Decl.
usbHandle = CreateFile(
interfacename,
GENERIC_WRITE,
FILE_SHARE_READ,
NULL,
OPEN_ALWAYS,
FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN,
NULL);
*/

usbHandle = FileIO.CreateFile(
interfaceName,
FileIO.FileAccess.GENERIC_WRITE | FileIO.FileAccess.GENERIC_READ,
FileIO.FileShareMode.FILE_SHARE_READ,
IntPtr.Zero,
FileIO.FileCreationDisposition.OPEN_ALWAYS,
FileIO.FileAttributes.FILE_ATTRIBUTE_NORMAL |
FileIO.FileAttributes.FILE_FLAG_SEQUENTIAL_SCAN |
FileIO.FileAttributes.FILE_FLAG_OVERLAPPED,
IntPtr.Zero);
if ((int)usbHandle <= 0)
throw new Win32Exception(Marshal.GetLastWin32Error());
}
else
if ((int)usbHandle > 0)
{
FileIO.CloseHandle(usbHandle);
usbHandle = IntPtr.Zero;
}
}

protected override bool GetConnected()
{
return ((int)usbHandle > 0);
}

public override bool BeginSend()
{
return GetConnected();
}

public override void EndSend()
{
// do nothing
}

public override int Send(byte[] buffer, int offset, int count)
{
// USB 1.1 WriteFile maximum block size is 4096
uint size;
byte[] bytes;

if (!GetConnected())
throw new Exception("Not connected");

if (count > 4096)
{
throw new NotImplementedException(); // TODO: Copy byte array loop
}
else
{
bytes = new byte[count];
Array.Copy(buffer, offset, bytes, 0, count);
ManualResetEvent wo = new ManualResetEvent(false);
NativeOverlapped ov = new NativeOverlapped();
// ov.OffsetLow = 0; ov.OffsetHigh = 0;
ov.EventHandle = wo.Handle;
if (!FileIO.WriteFile(usbHandle, bytes, (uint)count, out size, ref ov))
{
if (Marshal.GetLastWin32Error() == FileIO.ERROR_IO_PENDING)
wo.WaitOne(WriteTimeout, false);
else
throw new Win32Exception(Marshal.GetLastWin32Error());
}

FileIO.GetOverlappedResult(usbHandle, ref ov, out size, true);
return (int)size;
}
}

public override bool CanRead()
{
return true;
}

public override int Read(byte[] buffer, int offset, int count)
{
// USB 1.1 ReadFile in block chunks of 64 bytes
// USB 2.0 ReadFile in block chunks of 512 bytes
uint read;

if (readBuffer == null)
readBuffer = new byte[ReadBufferSize];

AutoResetEvent sg = new AutoResetEvent(false);
NativeOverlapped ov = new NativeOverlapped();
ov.OffsetLow = 0;
ov.OffsetHigh = 0;
ov.EventHandle = sg.Handle;

if (!FileIO.ReadFile(usbHandle, readBuffer, ReadBufferSize, out read, ref ov))
{
if (Marshal.GetLastWin32Error() == FileIO.ERROR_IO_PENDING)
sg.WaitOne(ReadTimeout, false);
else
throw new Win32Exception(Marshal.GetLastWin32Error());
}
FileIO.GetOverlappedResult(usbHandle, ref ov, out read, true);

Array.Copy(readBuffer, 0, buffer, offset, read);
return (int)read;
}

}

}


Wednesday, March 03, 2010

CCCalc

Conosco un molte persone che utilizzano una calcolatrice da tenere accanto al PC, o usano quella integrata nel telefono. Mi è sempre sembrato più furbo utilizzare direttamente il PC, ma non è sempre così immediato come la calcolatrice da tavolo o addirittura carta e penna.

La calcolatrice di windows è una sincera pena, tutti la conoscono e non sto nemmeno a parlarne.

Ho conosciuto invece un'eccellente calcolatore, poco noto, con un approccio nuovo e molto intuitivo riguardo all'interfaccia utente: CCCalc (http://cccalc.excelsior-usa.com/en/index.html).


Simula l'utilizzo di carta e penna, mettendo gli operandi "in colonna" come si farebbe su un foglio di carta. E' anche possibile modificare righe già scritte e vedere i risultati aggiornati. Per ora supporta solo le operazioni elementari: +, -, *, /, radice quadrata (shortcut: S) e %. Mancano altre funzioni scientifiche, ma sono meno usate dalla maggior parte degli utenti . Si impara subito ad usarlo ed ha la comodità di lasciare i risultati disponibili a video. In sostanza, è molto più semplice e comodo, per semplici calcoli, della calcolatrice di windows o di un foglio di calcolo come Calc/Excel. Ovviamente è gratuita.

Segnalo anche un'ottima calcolatrice scientifica, con capacità di disegno, conversioni, e valutazioni complesse: GraphCalc (http://www.graphcalc.com/), ormai non aggiornata da qualche anno, ma molto completa

Thursday, February 25, 2010

"Sandro Pertini - Presidente della Repubblica, 1978 - 1985. "Dietro ogni articolo della Carta Costituzionale stanno centinaia di giovani morti nella Resistenza, quindi la Repubblica è una conquista nostra e dobbiamo difenderla, costi quel che costi. Ma dobbiamo difenderla anche dalla corruzione. La corruzione è una nemica della Repubblica. I corrotti devono essere colpiti senza nessuna attenuante, senza nessuna pietà. E dare loro solidarietà, per ragioni di amicizia o di partito, significa diventare complici di questi corrotti ... Guai se qualcuno, per amicizia o solidarietà di partito, dovesse sostenere questi corrotti e difenderli... la legge sia implacabile, inflessibile contro i protagonisti di questi scandali, che danno un esempio veramente degradante al popolo italiano". Sarai sempre nei nostri cuori."

Il giorno dopo l'ennesimo scandalo (Fastweb-Telecom e la 'ndrangheta in Senato). Chi ha la forza oggi di dire queste parole?