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           DBG ("%s", "Setting config failed");
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         // Allocate memory for the device info and specification, fill it and return the info
00195         pus = malloc (sizeof (usb_spec_t));
00196         *pus = us;
00197         pnd = malloc (sizeof (nfc_device_t));
00198         strcpy (pnd->acName, target_name);
00199         pnd->nc = target_chip;
00200         pnd->nds = (nfc_device_spec_t) pus;
00201         pnd->bActive = true;
00202 
00203         // HACK1: Send first an ACK as Abort command, to reset chip before talking to it:
00204         pn53x_usb_ack (pnd);
00205 
00206         // HACK2: Then send a GetFirmware command to resync USB toggle bit between host & device
00207         // in case host used set_configuration and expects the device to have reset its toggle bit, which PN53x doesn't do
00208         byte_t  abtTx[] = { 0x00, 0x00, 0xff, 0x02, 0xfe, 0xd4, 0x02, 0x2a, 0x00 };
00209         byte_t  abtRx[BUFFER_LENGTH];
00210         int ret;
00211 #ifdef DEBUG
00212         PRINT_HEX ("TX", abtTx, sizeof(abtTx));
00213 #endif
00214         ret = usb_bulk_write (pus->pudh, pus->uiEndPointOut, (char *) abtTx, sizeof(abtTx), USB_TIMEOUT);
00215         if (ret < 0) {
00216           DBG ("usb_bulk_write failed with error %d", ret);
00217           usb_close (us.pudh);
00218           // we failed to use the specified device
00219           return NULL;
00220         }
00221         ret = usb_bulk_read (pus->pudh, pus->uiEndPointIn, (char *) abtRx, BUFFER_LENGTH, USB_TIMEOUT);
00222         if (ret < 0) {
00223           DBG ("usb_bulk_read failed with error %d", ret);
00224           usb_close (us.pudh);
00225           // we failed to use the specified device
00226           return NULL;
00227         }
00228 #ifdef DEBUG
00229         PRINT_HEX ("RX", abtRx, ret);
00230 #endif
00231         if (ret == 6) { // we got the ACK/NACK properly
00232           if (!pn53x_check_ack_frame_callback (pnd, abtRx, ret)) {
00233             DBG ("usb_bulk_read failed getting ACK");
00234             usb_close (us.pudh);
00235             // we failed to use the specified device
00236             return NULL;
00237           }
00238           ret = usb_bulk_read (pus->pudh, pus->uiEndPointIn, (char *) abtRx, BUFFER_LENGTH, USB_TIMEOUT);
00239           if (ret < 0) {
00240             DBG ("usb_bulk_read failed with error %d", ret);
00241             usb_close (us.pudh);
00242             // we failed to use the specified device
00243             return NULL;
00244           }
00245 #ifdef DEBUG
00246           PRINT_HEX ("RX", abtRx, ret);
00247 #endif
00248         }
00249 
00250         return pnd;
00251       }
00252     }
00253   }
00254   // We ran out of devices before the index required
00255   DBG ("%s", "Device index not found!");
00256   return NULL;
00257 }
00258 
00259 void
00260 pn53x_usb_disconnect (nfc_device_t * pnd)
00261 {
00262   usb_spec_t *pus = (usb_spec_t *) pnd->nds;
00263   int     ret;
00264 
00265   pn53x_usb_ack (pnd);
00266 
00267   if ((ret = usb_release_interface (pus->pudh, 0)) < 0) {
00268     ERR ("usb_release_interface failed (%i)", ret);
00269   }
00270 
00271   if ((ret = usb_close (pus->pudh)) < 0) {
00272     ERR ("usb_close failed (%i)", ret);
00273   }
00274 /*  
00275   if((ret = usb_reset(pus->pudh)) < 0) {
00276     ERR("usb_reset failed (%i, if errno: %s)",ret, strerror(-ret));
00277   }
00278 */
00279   free (pnd->nds);
00280   free (pnd);
00281 }
00282 
00283 bool
00284 pn53x_usb_transceive (nfc_device_t * pnd, const byte_t * pbtTx, const size_t szTx, byte_t * pbtRx, size_t * pszRx)
00285 {
00286   size_t  uiPos = 0;
00287   int     ret = 0;
00288   byte_t  abtTx[BUFFER_LENGTH] = { 0x00, 0x00, 0xff };  // Every packet must start with "00 00 ff"
00289   byte_t  abtRx[BUFFER_LENGTH];
00290   usb_spec_t *pus = (usb_spec_t *) pnd->nds;
00291   // TODO: Move this one level up for libnfc-1.6
00292   uint8_t ack_frame[] = { 0x00, 0x00, 0xff, 0x00, 0xff, 0x00 };
00293 
00294   // Packet length = data length (len) + checksum (1) + end of stream marker (1)
00295   abtTx[3] = szTx;
00296   // Packet length checksum 
00297   abtTx[4] = 0x0100 - abtTx[3];
00298   // Copy the PN53X command into the packet abtTx
00299   memmove (abtTx + 5, pbtTx, szTx);
00300 
00301   // Calculate data payload checksum
00302   abtTx[szTx + 5] = 0;
00303   for (uiPos = 0; uiPos < szTx; uiPos++) {
00304     abtTx[szTx + 5] -= abtTx[uiPos + 5];
00305   }
00306 
00307   // End of stream marker
00308   abtTx[szTx + 6] = 0;
00309 
00310 #ifdef DEBUG
00311   PRINT_HEX ("TX", abtTx, szTx + 7);
00312 #endif
00313 
00314   ret = usb_bulk_write (pus->pudh, pus->uiEndPointOut, (char *) abtTx, szTx + 7, USB_TIMEOUT);
00315   // HACK This little hack is a well know problem of USB, see http://www.libusb.org/ticket/6 for more details
00316   if ((ret % pus->wMaxPacketSize) == 0) {
00317     usb_bulk_write (pus->pudh, pus->uiEndPointOut, "\0", 0, USB_TIMEOUT);
00318   }
00319 
00320   if (ret < 0) {
00321     DBG ("usb_bulk_write failed with error %d", ret);
00322     pnd->iLastError = DEIO;
00323     return false;
00324   }
00325 
00326   ret = usb_bulk_read (pus->pudh, pus->uiEndPointIn, (char *) abtRx, BUFFER_LENGTH, USB_TIMEOUT);
00327   if (ret < 0) {
00328     DBG ("usb_bulk_read failed with error %d", ret);
00329     pnd->iLastError = DEIO;
00330     // try to interrupt current device state
00331     pn53x_usb_ack(pnd);
00332     return false;
00333   }
00334 #ifdef DEBUG
00335   PRINT_HEX ("RX", abtRx, ret);
00336 #endif
00337 
00338   if (!pn53x_check_ack_frame_callback (pnd, abtRx, ret))
00339     return false;
00340 
00341   ret = usb_bulk_read (pus->pudh, pus->uiEndPointIn, (char *) abtRx, BUFFER_LENGTH, USB_TIMEOUT);
00342   if (ret < 0) {
00343     DBG ("usb_bulk_read failed with error %d", ret);
00344     pnd->iLastError = DEIO;
00345     // try to interrupt current device state
00346     pn53x_usb_ack(pnd);
00347     return false;
00348   }
00349 #ifdef DEBUG
00350   PRINT_HEX ("RX", abtRx, ret);
00351 #endif
00352 
00353 #ifdef DEBUG
00354   PRINT_HEX ("TX", ack_frame, 6);
00355 #endif
00356   usb_bulk_write (pus->pudh, pus->uiEndPointOut, (char *) ack_frame, 6, USB_TIMEOUT);
00357 
00358   if (!pn53x_check_error_frame_callback (pnd, abtRx, ret))
00359     return false;
00360 
00361   // When the answer should be ignored, just return a succesful result
00362   if (pbtRx == NULL || pszRx == NULL)
00363     return true;
00364 
00365   // Only succeed when the result is at least 00 00 FF xx Fx Dx xx .. .. .. xx 00 (x = variable)
00366   if (ret < 9) {
00367     DBG ("%s", "No data");
00368     pnd->iLastError = DEINVAL;
00369     return false;
00370   }
00371   // Remove the preceding and appending bytes 00 00 FF xx Fx .. .. .. xx 00 (x = variable)
00372   *pszRx = ret - 7 - 2;
00373 
00374   memcpy (pbtRx, abtRx + 7, *pszRx);
00375 
00376   return true;
00377 }
00378 
00379 void
00380 pn53x_usb_ack (nfc_device_t * pnd)
00381 {
00382   usb_spec_t *pus = (usb_spec_t *) pnd->nds;
00383 #ifdef DEBUG
00384   PRINT_HEX ("TX", ack_frame, sizeof (ack_frame));
00385 #endif
00386   usb_bulk_write (pus->pudh, pus->uiEndPointOut, (char *) ack_frame, sizeof (ack_frame), USB_TIMEOUT);
00387 }