LCOV - code coverage report
Current view: top level - lkbce/drivers/usb/storage - sierra_ms.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 75 75 100.0 %
Date: 2017-01-25 Functions: 6 6 100.0 %

          Line data    Source code
       1             : #include <scsi/scsi.h>
       2             : #include <scsi/scsi_host.h>
       3             : #include <scsi/scsi_cmnd.h>
       4             : #include <scsi/scsi_device.h>
       5             : #include <linux/usb.h>
       6             : 
       7             : #include "usb.h"
       8             : #include "transport.h"
       9             : #include "protocol.h"
      10             : #include "scsiglue.h"
      11             : #include "sierra_ms.h"
      12             : #include "debug.h"
      13             : 
      14             : #define SWIMS_USB_REQUEST_SetSwocMode   0x0B
      15             : #define SWIMS_USB_REQUEST_GetSwocInfo   0x0A
      16             : #define SWIMS_USB_INDEX_SetMode         0x0000
      17             : #define SWIMS_SET_MODE_Modem            0x0001
      18             : 
      19             : #define TRU_NORMAL                      0x01
      20             : #define TRU_FORCE_MS                    0x02
      21             : #define TRU_FORCE_MODEM                 0x03
      22             : 
      23           1 : static unsigned int swi_tru_install = 1;
      24             : module_param(swi_tru_install, uint, S_IRUGO | S_IWUSR);
      25           1 : MODULE_PARM_DESC(swi_tru_install, "TRU-Install mode (1=Full Logic (def),"
      26             :                  " 2=Force CD-Rom, 3=Force Modem)");
      27             : 
      28             : struct swoc_info {
      29             :         __u8 rev;
      30             :         __u8 reserved[8];
      31             :         __u16 LinuxSKU;
      32             :         __u16 LinuxVer;
      33             :         __u8 reserved2[47];
      34             : } __attribute__((__packed__));
      35             : 
      36             : static bool containsFullLinuxPackage(struct swoc_info *swocInfo)
      37             : {
      38           6 :         if ((swocInfo->LinuxSKU >= 0x2100 && swocInfo->LinuxSKU <= 0x2FFF) ||
      39             :            (swocInfo->LinuxSKU >= 0x7100 && swocInfo->LinuxSKU <= 0x7FFF))
      40           1 :                 return true;
      41             :         else
      42           1 :                 return false;
      43             : }
      44             : 
      45             : static int sierra_set_ms_mode(struct usb_device *udev, __u16 eSWocMode)
      46             : {
      47           2 :         int result;
      48           2 :         US_DEBUGP("SWIMS: %s", "DEVICE MODE SWITCH\n");
      49           6 :         result = usb_control_msg(udev, usb_sndctrlpipe(udev, 0),
      50             :                         SWIMS_USB_REQUEST_SetSwocMode,  /* __u8 request      */
      51             :                         USB_TYPE_VENDOR | USB_DIR_OUT,  /* __u8 request type */
      52             :                         eSWocMode,                      /* __u16 value       */
      53             :                         0x0000,                         /* __u16 index       */
      54             :                         NULL,                           /* void *data        */
      55             :                         0,                              /* __u16 size        */
      56             :                         USB_CTRL_SET_TIMEOUT);          /* int timeout       */
      57           2 :         return result;
      58             : }
      59             : 
      60             : 
      61             : static int sierra_get_swoc_info(struct usb_device *udev,
      62             :                                 struct swoc_info *swocInfo)
      63           2 : {
      64           2 :         int result;
      65             : 
      66             :         US_DEBUGP("SWIMS: Attempting to get TRU-Install info.\n");
      67             : 
      68           6 :         result = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0),
      69             :                         SWIMS_USB_REQUEST_GetSwocInfo,  /* __u8 request      */
      70             :                         USB_TYPE_VENDOR | USB_DIR_IN,   /* __u8 request type */
      71             :                         0,                              /* __u16 value       */
      72             :                         0,                              /* __u16 index       */
      73             :                         (void *) swocInfo,              /* void *data        */
      74             :                         sizeof(struct swoc_info),       /* __u16 size        */
      75             :                         USB_CTRL_SET_TIMEOUT);          /* int timeout       */
      76             : 
      77           2 :         swocInfo->LinuxSKU = le16_to_cpu(swocInfo->LinuxSKU);
      78           2 :         swocInfo->LinuxVer = le16_to_cpu(swocInfo->LinuxVer);
      79           2 :         return result;
      80             : }
      81             : 
      82             : static void debug_swoc(struct swoc_info *swocInfo)
      83             : {
      84           2 :         US_DEBUGP("SWIMS: SWoC Rev: %02d \n", swocInfo->rev);
      85             :         US_DEBUGP("SWIMS: Linux SKU: %04X \n", swocInfo->LinuxSKU);
      86             :         US_DEBUGP("SWIMS: Linux Version: %04X \n", swocInfo->LinuxVer);
      87             : }
      88             : 
      89             : 
      90             : static ssize_t show_truinst(struct device *dev, struct device_attribute *attr,
      91             :                         char *buf)
      92           1 : {
      93           1 :         struct swoc_info *swocInfo;
      94           3 :         struct usb_interface *intf = to_usb_interface(dev);
      95           3 :         struct usb_device *udev = interface_to_usbdev(intf);
      96           1 :         int result;
      97           3 :         if (swi_tru_install == TRU_FORCE_MS) {
      98           2 :                 result = snprintf(buf, PAGE_SIZE, "Forced Mass Storage\n");
      99             :         } else {
     100           3 :                 swocInfo = kmalloc(sizeof(struct swoc_info), GFP_KERNEL);
     101           2 :                 if (!swocInfo) {
     102             :                         US_DEBUGP("SWIMS: Allocation failure\n");
     103           1 :                         snprintf(buf, PAGE_SIZE, "Error\n");
     104           1 :                         return -ENOMEM;
     105             :                 }
     106           2 :                 result = sierra_get_swoc_info(udev, swocInfo);
     107           2 :                 if (result < 0) {
     108             :                         US_DEBUGP("SWIMS: failed SWoC query\n");
     109           1 :                         kfree(swocInfo);
     110           1 :                         snprintf(buf, PAGE_SIZE, "Error\n");
     111           1 :                         return -EIO;
     112             :                 }
     113           2 :                 debug_swoc(swocInfo);
     114           4 :                 result = snprintf(buf, PAGE_SIZE,
     115             :                         "REV=%02d SKU=%04X VER=%04X\n",
     116             :                         swocInfo->rev,
     117             :                         swocInfo->LinuxSKU,
     118             :                         swocInfo->LinuxVer);
     119           1 :                 kfree(swocInfo);
     120             :         }
     121           2 :         return result;
     122             : }
     123           1 : static DEVICE_ATTR(truinst, S_IRUGO, show_truinst, NULL);
     124             : 
     125             : int sierra_ms_init(struct us_data *us)
     126             : {
     127           1 :         int result, retries;
     128           1 :         signed long delay_t;
     129           1 :         struct swoc_info *swocInfo;
     130           1 :         struct usb_device *udev;
     131           1 :         struct Scsi_Host *sh;
     132           1 :         struct scsi_device *sd;
     133           1 : 
     134           2 :         delay_t = 2;
     135           2 :         retries = 3;
     136           2 :         result = 0;
     137           1 :         udev = us->pusb_dev;
     138             : 
     139           2 :         sh = us_to_host(us);
     140           1 :         sd = scsi_get_host_dev(sh);
     141             : 
     142             :         US_DEBUGP("SWIMS: sierra_ms_init called\n");
     143             : 
     144             :         /* Force Modem mode */
     145           2 :         if (swi_tru_install == TRU_FORCE_MODEM) {
     146             :                 US_DEBUGP("SWIMS: %s", "Forcing Modem Mode\n");
     147           2 :                 result = sierra_set_ms_mode(udev, SWIMS_SET_MODE_Modem);
     148             :                 if (result < 0)
     149             :                         US_DEBUGP("SWIMS: Failed to switch to modem mode.\n");
     150           1 :                 return -EIO;
     151             :         }
     152             :         /* Force Mass Storage mode (keep CD-Rom) */
     153           2 :         else if (swi_tru_install == TRU_FORCE_MS) {
     154             :                 US_DEBUGP("SWIMS: %s", "Forcing Mass Storage Mode\n");
     155             :                 goto complete;
     156             :         }
     157             :         /* Normal TRU-Install Logic */
     158             :         else {
     159             :                 US_DEBUGP("SWIMS: %s", "Normal SWoC Logic\n");
     160             : 
     161           3 :                 swocInfo = kmalloc(sizeof(struct swoc_info),
     162             :                                 GFP_KERNEL);
     163           2 :                 if (!swocInfo) {
     164             :                         US_DEBUGP("SWIMS: %s", "Allocation failure\n");
     165           1 :                         return -ENOMEM;
     166             :                 }
     167             : 
     168           1 :                 retries = 3;
     169           1 :                 do {
     170           1 :                         retries--;
     171           2 :                         result = sierra_get_swoc_info(udev, swocInfo);
     172           2 :                         if (result < 0) {
     173             :                                 US_DEBUGP("SWIMS: %s", "Failed SWoC query\n");
     174           1 :                                 schedule_timeout_uninterruptible(2*HZ);
     175             :                         }
     176           4 :                 } while (retries && result < 0);
     177             : 
     178           3 :                 if (result < 0) {
     179             :                         US_DEBUGP("SWIMS: %s",
     180             :                                   "Completely failed SWoC query\n");
     181           1 :                         kfree(swocInfo);
     182           1 :                         return -EIO;
     183             :                 }
     184             : 
     185           2 :                 debug_swoc(swocInfo);
     186             : 
     187             :                 /* If there is not Linux software on the TRU-Install device
     188             :                  * then switch to modem mode
     189             :                  */
     190           8 :                 if (!containsFullLinuxPackage(swocInfo)) {
     191             :                         US_DEBUGP("SWIMS: %s",
     192             :                                 "Switching to Modem Mode\n");
     193           2 :                         result = sierra_set_ms_mode(udev,
     194             :                                 SWIMS_SET_MODE_Modem);
     195             :                         if (result < 0)
     196             :                                 US_DEBUGP("SWIMS: Failed to switch modem\n");
     197           1 :                         kfree(swocInfo);
     198           1 :                         return -EIO;
     199             :                 }
     200           1 :                 kfree(swocInfo);
     201             :         }
     202             : complete:
     203           2 :         result = device_create_file(&us->pusb_intf->dev, &dev_attr_truinst);
     204             : 
     205           2 :         return 0;
     206             : }
     207             : 

Generated by: LCOV version 1.10