pn53x_usb.c

Go to the documentation of this file.
00001 /*-
00002  * Public platform independent Near Field Communication (NFC) library
00003  * 
00004  * Copyright (C) 2009, Roel Verdult
00005  * Copyright (C) 2010, Romain Tartière, Romuald Conty
00006  * 
00007  * This program is free software: you can redistribute it and/or modify it
00008  * under the terms of the GNU Lesser General Public License as published by the
00009  * Free Software Foundation, either version 3 of the License, or (at your
00010  * option) any later version.
00011  * 
00012  * This program is distributed in the hope that it will be useful, but WITHOUT
00013  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
00014  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
00015  * more details.
00016  *
00017  * You should have received a copy of the GNU Lesser General Public License
00018  * along with this program.  If not, see <http://www.gnu.org/licenses/>
00019  */
00020 
00026 #ifdef HAVE_CONFIG_H
00027 #  include "config.h"
00028 #endif // HAVE_CONFIG_H
00029 
00030 /*
00031 Thanks to d18c7db and Okko for example code
00032 */
00033 
00034 #include <stdio.h>
00035 #include <stdlib.h>
00036 #include <usb.h>
00037 #include <string.h>
00038 
00039 #include "../drivers.h"
00040 #include "../chips/pn53x.h"
00041 
00042 #include <nfc/nfc.h>
00043 #include <nfc/nfc-messages.h>
00044 
00045 #define BUFFER_LENGTH 256
00046 #define USB_TIMEOUT   0
00047 
00048 // TODO Move this HACK1 into an upper level in order to benefit to other devices that use PN53x
00049 static const byte_t ack_frame[] = { 0x00, 0x00, 0xff, 0x00, 0xff, 0x00 };
00050 
00051 void pn53x_usb_ack (nfc_device_t * pnd);
00052 
00053 // Find transfer endpoints for bulk transfers
00054 void
00055 get_end_points (struct usb_device *dev, usb_spec_t * pus)
00056 {
00057   uint32_t uiIndex;
00058   uint32_t uiEndPoint;
00059   struct usb_interface_descriptor *puid = dev->config->interface->altsetting;
00060 
00061   // 3 Endpoints maximum: Interrupt In, Bulk In, Bulk Out
00062   for (uiIndex = 0; uiIndex < puid->bNumEndpoints; uiIndex++) {
00063     // Only accept bulk transfer endpoints (ignore interrupt endpoints)
00064     if (puid->endpoint[uiIndex].bmAttributes != USB_ENDPOINT_TYPE_BULK)
00065       continue;
00066 
00067     // Copy the endpoint to a local var, makes it more readable code
00068     uiEndPoint = puid->endpoint[uiIndex].bEndpointAddress;
00069 
00070     // Test if we dealing with a bulk IN endpoint
00071     if ((uiEndPoint & USB_ENDPOINT_DIR_MASK) == USB_ENDPOINT_IN) {
00072       pus->uiEndPointIn = uiEndPoint;
00073       pus->wMaxPacketSize = puid->endpoint[uiIndex].wMaxPacketSize;
00074     }
00075     // Test if we dealing with a bulk OUT endpoint
00076     if ((uiEndPoint & USB_ENDPOINT_DIR_MASK) == USB_ENDPOINT_OUT) {
00077       pus->uiEndPointOut = uiEndPoint;
00078       pus->wMaxPacketSize = puid->endpoint[uiIndex].wMaxPacketSize;
00079     }
00080   }
00081 }
00082 
00083 bool
00084 pn53x_usb_list_devices (nfc_device_desc_t pnddDevices[], size_t szDevices, size_t * pszDeviceFound,
00085                         usb_candidate_t candidates[], int num_candidates, char *target_name)
00086 {
00087   int     ret,
00088           i;
00089 
00090   struct usb_bus *bus;
00091   struct usb_device *dev;
00092   usb_dev_handle *udev;
00093   uint32_t uiBusIndex = 0;
00094   char    string[256];
00095 
00096   string[0] = '\0';
00097   usb_init ();
00098 
00099   // usb_find_busses will find all of the busses on the system. Returns the number of changes since previous call to this function (total of new busses and busses removed).
00100   if ((ret = usb_find_busses () < 0))
00101     return false;
00102   // usb_find_devices will find all of the devices on each bus. This should be called after usb_find_busses. Returns the number of changes since the previous call to this function (total of new device and devices removed).
00103   if ((ret = usb_find_devices () < 0))
00104     return false;
00105 
00106   *pszDeviceFound = 0;
00107 
00108   for (bus = usb_get_busses (); bus; bus = bus->next) {
00109     for (dev = bus->devices; dev; dev = dev->next, uiBusIndex++) {
00110       for (i = 0; i < num_candidates; ++i) {
00111         // DBG("Checking device %04x:%04x (%04x:%04x)",dev->descriptor.idVendor,dev->descriptor.idProduct,candidates[i].idVendor,candidates[i].idProduct);
00112         if (candidates[i].idVendor == dev->descriptor.idVendor && candidates[i].idProduct == dev->descriptor.idProduct) {
00113           // Make sure there are 2 endpoints available
00114           // with libusb-win32 we got some null pointers so be robust before looking at endpoints:
00115           if (dev->config == NULL || dev->config->interface == NULL || dev->config->interface->altsetting == NULL) {
00116             // Nope, we maybe want the next one, let's try to find another
00117             continue;
00118           }
00119           if (dev->config->interface->altsetting->bNumEndpoints < 2) {
00120             // Nope, we maybe want the next one, let's try to find another
00121             continue;
00122           }
00123           if (dev->descriptor.iManufacturer || dev->descriptor.iProduct) {
00124             udev = usb_open (dev);
00125             if (udev) {
00126               usb_get_string_simple (udev, dev->descriptor.iManufacturer, string, sizeof (string));
00127               if (strlen (string) > 0)
00128                 strcpy (string + strlen (string), " / ");
00129               usb_get_string_simple (udev, dev->descriptor.iProduct, string + strlen (string),
00130                                      sizeof (string) - strlen (string));
00131             }
00132             usb_close (udev);
00133           }
00134           if (strlen (string) == 0)
00135             strcpy (pnddDevices[*pszDeviceFound].acDevice, target_name);
00136           else
00137             strcpy (pnddDevices[*pszDeviceFound].acDevice, string);
00138           pnddDevices[*pszDeviceFound].pcDriver = target_name;
00139           pnddDevices[*pszDeviceFound].uiBusIndex = uiBusIndex;
00140           (*pszDeviceFound)++;
00141           // Test if we reach the maximum "wanted" devices
00142           if ((*pszDeviceFound) == szDevices) {
00143             return true;
00144           }
00145         }
00146       }
00147     }
00148   }
00149   if (*pszDeviceFound)
00150     return true;
00151   return false;
00152 }
00153 
00154 nfc_device_t *
00155 pn53x_usb_connect (const nfc_device_desc_t * pndd, const char *target_name, int target_chip)
00156 {
00157   nfc_device_t *pnd = NULL;
00158   usb_spec_t *pus;
00159   usb_spec_t us;
00160   struct usb_bus *bus;
00161   struct usb_device *dev;
00162   uint32_t uiBusIndex;
00163 
00164   us.uiEndPointIn = 0;
00165   us.uiEndPointOut = 0;
00166   us.pudh = NULL;
00167 
00168   DBG ("Attempt to connect to %s device", target_name);
00169   usb_init ();
00170 
00171   uiBusIndex = pndd->uiBusIndex;
00172 
00173   for (bus = usb_get_busses (); bus; bus = bus->next) {
00174     for (dev = bus->devices; dev; dev = dev->next, uiBusIndex--) {
00175       DBG ("Checking device %04x:%04x", dev->descriptor.idVendor, dev->descriptor.idProduct);
00176       if (uiBusIndex == 0) {
00177         // Open the USB device
00178         us.pudh = usb_open (dev);
00179 
00180         get_end_points (dev, &us);
00181         if (usb_set_configuration (us.pudh, 1) < 0) {
00182           ERR ("Unable to set USB configuration, please check USB permissions for device %04x:%04x", dev->descriptor.idVendor, dev->descriptor.idProduct);
00183           usb_close (us.pudh);
00184           // we failed to use the specified device
00185           return NULL;
00186         }
00187 
00188         if (usb_claim_interface (us.pudh, 0) < 0) {
00189           DBG ("%s", "Can't claim interface");
00190           usb_close (us.pudh);
00191           // we failed to use the specified device
00192           return NULL;
00193         }
00194         // Copy VendorId and ProductId
00195         us.uc.idVendor = dev->descriptor.idVendor;
00196         us.uc.idProduct = dev->descriptor.idProduct;
00197         // Allocate memory for the device info and specification, fill it and return the info
00198         pus = malloc (sizeof (usb_spec_t));
00199         *pus = us;
00200         pnd = malloc (sizeof (nfc_device_t));
00201         strcpy (pnd->acName, target_name);
00202         pnd->nc = target_chip;
00203         pnd->nds = (nfc_device_spec_t) pus;
00204         pnd->bActive = true;
00205 
00206         // HACK1: Send first an ACK as Abort command, to reset chip before talking to it:
00207         pn53x_usb_ack (pnd);
00208 
00209         // HACK2: Then send a GetFirmware command to resync USB toggle bit between host & device
00210         // in case host used set_configuration and expects the device to have reset its toggle bit, which PN53x doesn't do
00211         byte_t  abtTx[] = { 0x00, 0x00, 0xff, 0x02, 0xfe, 0xd4, 0x02, 0x2a, 0x00 };
00212         byte_t  abtRx[BUFFER_LENGTH];
00213         int ret;
00214 #ifdef DEBUG
00215         PRINT_HEX ("TX", abtTx, sizeof(abtTx));
00216 #endif
00217         ret = usb_bulk_write (pus->pudh, pus->uiEndPointOut, (char *) abtTx, sizeof(abtTx), USB_TIMEOUT);
00218         if (ret < 0) {
00219           DBG ("usb_bulk_write failed with error %d", ret);
00220           usb_close (us.pudh);
00221           // we failed to use the specified device
00222           return NULL;
00223         }
00224         ret = usb_bulk_read (pus->pudh, pus->uiEndPointIn, (char *) abtRx, BUFFER_LENGTH, USB_TIMEOUT);
00225         if (ret < 0) {
00226           DBG ("usb_bulk_read failed with error %d", ret);
00227           usb_close (us.pudh);
00228           // we failed to use the specified device
00229           return NULL;
00230         }
00231 #ifdef DEBUG
00232         PRINT_HEX ("RX", abtRx, ret);
00233 #endif
00234         if (ret == 6) { // we got the ACK/NACK properly
00235           if (!pn53x_check_ack_frame_callback (pnd, abtRx, ret)) {
00236             DBG ("usb_bulk_read failed getting ACK");
00237             usb_close (us.pudh);
00238             // we failed to use the specified device
00239             return NULL;
00240           }
00241           ret = usb_bulk_read (pus->pudh, pus->uiEndPointIn, (char *) abtRx, BUFFER_LENGTH, USB_TIMEOUT);
00242           if (ret < 0) {
00243             DBG ("usb_bulk_read failed with error %d", ret);
00244             usb_close (us.pudh);
00245             // we failed to use the specified device
00246             return NULL;
00247           }
00248 #ifdef DEBUG
00249           PRINT_HEX ("RX", abtRx, ret);
00250 #endif
00251         }
00252 
00253         return pnd;
00254       }
00255     }
00256   }
00257   // We ran out of devices before the index required
00258   DBG ("%s", "Device index not found!");
00259   return NULL;
00260 }
00261 
00262 void
00263 pn53x_usb_disconnect (nfc_device_t * pnd)
00264 {
00265   usb_spec_t *pus = (usb_spec_t *) pnd->nds;
00266   int     ret;
00267 
00268   pn53x_usb_ack (pnd);
00269 
00270   if ((ret = usb_release_interface (pus->pudh, 0)) < 0) {
00271     ERR ("usb_release_interface failed (%i)", ret);
00272   }
00273 
00274   if ((ret = usb_close (pus->pudh)) < 0) {
00275     ERR ("usb_close failed (%i)", ret);
00276   }
00277 /*  
00278   if((ret = usb_reset(pus->pudh)) < 0) {
00279     ERR("usb_reset failed (%i, if errno: %s)",ret, strerror(-ret));
00280   }
00281 */
00282   free (pnd->nds);
00283   free (pnd);
00284 }
00285 
00286 bool
00287 pn53x_usb_transceive (nfc_device_t * pnd, const byte_t * pbtTx, const size_t szTx, byte_t * pbtRx, size_t * pszRx)
00288 {
00289   size_t  uiPos = 0;
00290   int     ret = 0;
00291   byte_t  abtTx[BUFFER_LENGTH] = { 0x00, 0x00, 0xff };  // Every packet must start with "00 00 ff"
00292   byte_t  abtRx[BUFFER_LENGTH];
00293   usb_spec_t *pus = (usb_spec_t *) pnd->nds;
00294   // TODO: Move this one level up for libnfc-1.6
00295   uint8_t ack_frame[] = { 0x00, 0x00, 0xff, 0x00, 0xff, 0x00 };
00296 
00297   // Packet length = data length (len) + checksum (1) + end of stream marker (1)
00298   abtTx[3] = szTx;
00299   // Packet length checksum 
00300   abtTx[4] = 0x0100 - abtTx[3];
00301   // Copy the PN53X command into the packet abtTx
00302   memmove (abtTx + 5, pbtTx, szTx);
00303 
00304   // Calculate data payload checksum
00305   abtTx[szTx + 5] = 0;
00306   for (uiPos = 0; uiPos < szTx; uiPos++) {
00307     abtTx[szTx + 5] -= abtTx[uiPos + 5];
00308   }
00309 
00310   // End of stream marker
00311   abtTx[szTx + 6] = 0;
00312 
00313 #ifdef DEBUG
00314   PRINT_HEX ("TX", abtTx, szTx + 7);
00315 #endif
00316 
00317   ret = usb_bulk_write (pus->pudh, pus->uiEndPointOut, (char *) abtTx, szTx + 7, USB_TIMEOUT);
00318   // HACK This little hack is a well know problem of USB, see http://www.libusb.org/ticket/6 for more details
00319   if ((ret % pus->wMaxPacketSize) == 0) {
00320     usb_bulk_write (pus->pudh, pus->uiEndPointOut, "\0", 0, USB_TIMEOUT);
00321   }
00322 
00323   if (ret < 0) {
00324     DBG ("usb_bulk_write failed with error %d", ret);
00325     pnd->iLastError = DEIO;
00326     return false;
00327   }
00328 
00329   ret = usb_bulk_read (pus->pudh, pus->uiEndPointIn, (char *) abtRx, BUFFER_LENGTH, USB_TIMEOUT);
00330   if (ret < 0) {
00331     DBG ("usb_bulk_read failed with error %d", ret);
00332     pnd->iLastError = DEIO;
00333     // try to interrupt current device state
00334     pn53x_usb_ack(pnd);
00335     return false;
00336   }
00337 #ifdef DEBUG
00338   PRINT_HEX ("RX", abtRx, ret);
00339 #endif
00340 
00341   if (!pn53x_check_ack_frame_callback (pnd, abtRx, ret))
00342     return false;
00343 
00344   ret = usb_bulk_read (pus->pudh, pus->uiEndPointIn, (char *) abtRx, BUFFER_LENGTH, USB_TIMEOUT);
00345   if (ret < 0) {
00346     DBG ("usb_bulk_read failed with error %d", ret);
00347     pnd->iLastError = DEIO;
00348     // try to interrupt current device state
00349     pn53x_usb_ack(pnd);
00350     return false;
00351   }
00352 #ifdef DEBUG
00353   PRINT_HEX ("RX", abtRx, ret);
00354 #endif
00355 
00356 #ifdef DEBUG
00357   PRINT_HEX ("TX", ack_frame, 6);
00358 #endif
00359   usb_bulk_write (pus->pudh, pus->uiEndPointOut, (char *) ack_frame, 6, USB_TIMEOUT);
00360 
00361   if (!pn53x_check_error_frame_callback (pnd, abtRx, ret))
00362     return false;
00363 
00364   // When the answer should be ignored, just return a succesful result
00365   if (pbtRx == NULL || pszRx == NULL)
00366     return true;
00367 
00368   // Only succeed when the result is at least 00 00 FF xx Fx Dx xx .. .. .. xx 00 (x = variable)
00369   if (ret < 9) {
00370     DBG ("%s", "No data");
00371     pnd->iLastError = DEINVAL;
00372     return false;
00373   }
00374   // Remove the preceding and appending bytes 00 00 FF xx Fx .. .. .. xx 00 (x = variable)
00375   *pszRx = ret - 7 - 2;
00376 
00377   memcpy (pbtRx, abtRx + 7, *pszRx);
00378 
00379   return true;
00380 }
00381 
00382 void
00383 pn53x_usb_ack (nfc_device_t * pnd)
00384 {
00385   usb_spec_t *pus = (usb_spec_t *) pnd->nds;
00386 #ifdef DEBUG
00387   PRINT_HEX ("TX", ack_frame, sizeof (ack_frame));
00388 #endif
00389   usb_bulk_write (pus->pudh, pus->uiEndPointOut, (char *) ack_frame, sizeof (ack_frame), USB_TIMEOUT);
00390 }